Select
nexvyn/selectFreeComponent
A form select with a two-layer proximity highlight (selected accent tint + muted hover), drawn check animation, and a trigger label morph on selection change.
Live preview
live · rendered by the registry
Rendered by nexvyn on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://ui.nexvyn.dev/r/select.jsonSource
1'use client'23import {4 Children,5 cloneElement,6 createContext,7 forwardRef,8 isValidElement,9 useCallback,10 useContext,11 useEffect,12 useId,13 useLayoutEffect,14 useMemo,15 useRef,16 useState,17 type HTMLAttributes,18 type ReactElement,19 type ReactNode,20} from 'react'21import { createPortal } from 'react-dom'22import { AnimatePresence, motion, useReducedMotion, type MotionValue } from 'motion/react'23import { cn } from '@/lib/utils'24import { useMounted } from '@/hooks/use-mounted'25import { playHoverSound, playClickSound } from '@/lib/sound'26import { springs } from '@/lib/motion-tokens'27import { useProximityHighlight, ProximityHighlight } from '@/lib/hooks/use-proximity-highlight'28const MAX_HEIGHT = 32029const SIDE_OFFSET = 830const VIEWPORT_MARGIN = 1231const TYPEAHEAD_RESET_MS = 50032interface SelectContextValue {33 value: string34 setValue: (v: string) => void35 open: boolean36 setOpen: (next: boolean) => void37 disabled: boolean38 triggerId: string39 contentId: string40 labelMap: React.MutableRefObject<Map<string, string>>41 registerOption: (value: string, label: string) => void42 openInteractionRef: React.MutableRefObject<'keyboard' | 'pointer'>43 itemsWidth: number | null44 setItemsWidth: (w: number | null) => void45}4647const SelectContext = createContext<SelectContextValue | null>(null)4849function useSelectCtx(componentName: string) {50 const ctx = useContext(SelectContext)51 if (!ctx) throw new Error(`${componentName} must be used within <Select>`)52 return ctx53}54interface SelectContentContextValue {55 activeIndex: number | null56 setActiveIndex: (i: number | null) => void57 highlightX: ReturnType<typeof import('motion/react').useSpring>58 highlightSize: MotionValue<number>59 highlightOpacity: ReturnType<typeof import('motion/react').useSpring>60 axis: 'x' | 'y'61 focusedIndex: number62 setFocusedIndex: (i: number) => void63 setOpen: (next: boolean) => void64 registerItem: (index: number, el: HTMLElement | null) => void65}6667const SelectContentContext = createContext<SelectContentContextValue | null>(null)6869function useSelectContentCtx(componentName: string) {70 const ctx = useContext(SelectContentContext)71 if (!ctx) throw new Error(`${componentName} must be used within <SelectContent>`)72 return ctx73}74function normalizeTypeahead(value: string) {75 return value76 .normalize('NFKD')77 .replace(/[\u0300-\u036f]/g, '')78 .toLowerCase()79 .replace(/\s+/g, ' ')80 .trim()81}8283function clamp(value: number, min: number, max: number) {84// … truncated
What it pulls in
npm packages
Files it writes
More from nexvyn
All 33 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Badgebadge | nexvyn | Components | Free | 2 deps · 2 files | |
| Bars Themebars-theme | nexvyn | Components | Free | 1 dep · 3 files | |
| Bounce Sidebarbounce-sidebar | nexvyn | Components | Free | 1 dep · 2 files | |
| Breadcrumbsbreadcrumbs | nexvyn | Components | Free | 1 dep · 2 files | |
| Checkboxcheckbox | nexvyn | Components | Free | 1 dep · 3 files | |
| Clipboard Fieldclipboard-field | nexvyn | Components | Free | no deps · 2 files | |
| Color Pickercolor-picker | nexvyn | Components | Free | no deps · 16 files | |
| Comboboxcombobox | nexvyn | Components | Free | 1 dep · 2 files |
