Select
fluid-functionalism/selectFreeComponent
Animated select menu with collision-aware positioning, typeahead, proximity hover, spring-animated popover, and animated checkmark. Radix flavor.
Install it
npx shadcn@latest add https://fluidfunctionalism.com/r/select.jsonSource
1"use client";23import {4 forwardRef,5 useRef,6 useEffect,7 useState,8 useCallback,9 useMemo,10 createContext,11 useContext,12 type ReactNode,13 type HTMLAttributes,14} from "react";15import { motion, AnimatePresence } from "framer-motion";16import { cva, type VariantProps } from "class-variance-authority";17import * as SelectPrimitive from "@radix-ui/react-select";18import type { IconComponent } from "@/lib/icon-context";19import { cn } from "@/lib/utils";20import { spring, exitFallbackMs } from "@/lib/springs";21import { useProximityHover } from "@/hooks/use-proximity-hover";22import { useShape } from "@/lib/shape-context";23import { Elevated } from "@/lib/elevated";2425// ---------------------------------------------------------------------------26// Select context27//28// Built on Radix Select, which owns positioning (popper collision flipping),29// dismissal (outside press, Escape), list keyboard navigation + typeahead30// (open and closed), combobox ARIA, and the hidden native <select> for forms.31// This layer keeps the proximity-hover overlays, the32// spring open/close animation, and the animated checkmark.33//34// Radix-specific notes (verified against @radix-ui/react-select 2.2.6 dist):35//36// - Value/placeholder: Radix shows the placeholder when its value is "" or37// undefined, so the root is *always controlled* with our string state38// ("" = no selection). Passing "" never flips controlled/uncontrolled, and39// `data-placeholder` lands on the Trigger (not the Value span) — hence the40// `group-data-[placeholder]:` variant on the value wrapper below.41//42// - Initial label: while closed, Radix renders Content's children into a43// detached DocumentFragment; the selected SelectItem/ItemText therefore44// mounts before the popup ever opens and portals its text into the Value45// node. No item traversal is needed — SelectContent just has to render46// unconditionally, never gated behind a47// local mounted flag.48//49// - Exit animation: Radix Select has no Presence/forceMount, so the popup50// unmounts the instant its `open` flips false. The root therefore keeps two51// open states: `open` (immediate, drives the motion targets) and52// `radixOpen` (what Radix sees; released via `unmount()` once the exit53// tween finishes).54//55// - Radix Select is modal-ish: it scroll-locks the page and disables outside56// pointer events while open. The Viewport's injected57// stylesheet hides its own scrollbar, which would leave long lists with no58// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from fluid-functionalism
All 53 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Accordionaccordion | fluid-functionalism | Components | Free | 3 deps | |
| Accordion (Base UI)accordion-base | fluid-functionalism | Components | Free | 3 deps | |
| Ask User Questionsask-user-questions | fluid-functionalism | Components | Free | 2 deps | |
| Badgebadge | fluid-functionalism | Components | Free | 1 dep | |
| Buttonbutton | fluid-functionalism | Components | Free | 4 deps | |
| Button (Base UI)button-base | fluid-functionalism | Components | Free | 4 deps | |
| Cardcard | fluid-functionalism | Components | Free | 1 dep | |
| Chat Messagechat-message | fluid-functionalism | Components | Free | 1 dep |
