Form Select
atroui/form-selectFreeComponent
Accessible select built on Base UI.
Install it
npx shadcn@latest add https://atroui.com/r/form-select.jsonSource
1"use client"23import { Select } from "@base-ui/react/select"4import { ChevronDown } from "lucide-react"5import { useMemo } from "react"67import { cn } from "@/lib/utils"89export type FormSelectOption = { value: string; label: string }1011type FormSelectProps = {12 id?: string13 value: string14 onValueChange: (value: string) => void15 options: FormSelectOption[]16 placeholder?: string17 disabled?: boolean18 className?: string19}2021export function FormSelect({22 id,23 value,24 onValueChange,25 options,26 placeholder = "Choose…",27 disabled,28 className,29}: FormSelectProps) {30 const labelByValue = useMemo(31 () => Object.fromEntries(options.map((o) => [o.value, o.label])),32 [options]33 )3435 return (36 <Select.Root37 value={value}38 onValueChange={(v) => onValueChange(v ?? "")}39 disabled={disabled}40 >41 <Select.Trigger42 id={id}43 className={cn(44 "flex w-full items-center justify-between gap-2 border border-border-subtle bg-background px-3.5 py-2.5 text-left text-base text-foreground sm:text-sm",45 "transition-[border-color,box-shadow] duration-200",46 "focus-visible:border-ring focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/20",47 "data-popup-open:border-ring data-popup-open:ring-2 data-popup-open:ring-ring/20",48 "disabled:cursor-not-allowed disabled:opacity-60",49 className50 )}51 >52 <span className="min-w-0 flex-1 truncate">53 <Select.Value placeholder={placeholder}>54 {(v) => {55 const key = v == null ? "" : String(v)56 return labelByValue[key] ?? placeholder57 }}58 </Select.Value>59 </span>60 <Select.Icon className="pointer-events-none shrink-0 text-muted-foreground">61 <ChevronDown className="size-4" aria-hidden />62 </Select.Icon>63 </Select.Trigger>64 <Select.Portal>65 <Select.Positioner className="z-100" sideOffset={6} align="start">66 <Select.Popup67 className={cn(68 "max-h-[min(320px,var(--available-height))] min-w-(--anchor-width) overflow-hidden rounded-lg border border-border-subtle bg-surface py-1 shadow-md outline-none",69 "origin-(--transform-origin)"70 )}71 >72 <Select.List className="max-h-[min(280px,var(--available-height))] scroll-py-1 overflow-y-auto p-1 outline-none">73 {options.map((opt) => (74 <Select.Item75// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from atroui
All 81 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Breadcrumbsbreadcrumbs | atroui | Components | Free | 2 deps | |
| Buttonbutton | atroui | Components | Free | 2 deps | |
| Cardcard | atroui | Components | Free | no deps | |
| Fade Infade-in | atroui | Components | Free | 1 dep | |
| Founder Avatarfounder-avatar | atroui | Components | Free | 1 dep | |
| Logologo | atroui | Components | Free | no deps | |
| Mockup Framemockup-frame | atroui | Components | Free | no deps | |
| Proseprose | atroui | Components | Free | no deps |
