Select
Choose one value from a compact, keyboard-accessible menu.
Preview
Use Select when a single choice belongs in a compact menu. Prefer Radio Group when all choices should stay visible, and Native Select when browser-native behavior is more useful than a custom popup. Searchable and multiple selection are outside this component's scope.
Opened when you sign in.
Installation
pnpm dlx shadcn@latest add http://127.0.0.1:3017/r/select.jsonInstalls the Select source, Radix Select, and Lucide icons. Uses your existing cn utility and semantic palette. Field and the optional Migoy theme are separate items. The URL is a local development snapshot.
Usage
import {
Select, SelectContent, SelectGroup, SelectItem, SelectLabel,
SelectSeparator, SelectTrigger, SelectValue,
} from '@/components/ui/select';Migoy follows the Radix Select API, consistent with the rest of this registry. The shadcn Base UI example is a composition reference, not an interchangeable API: there is no items prop or alignItemWithTrigger. Use value / defaultValue and onValueChange on Select. Place every SelectItem inside a SelectGroup. Item values must be unique, non-empty strings; reserve the empty root value for clearing back to the placeholder.
Composition
Select owns selection and form state. Compose the trigger and popup as siblings inside it:
Select
├── SelectTrigger
│ └── SelectValue
└── SelectContent
└── SelectGroup
├── SelectLabel (optional)
└── SelectItem (repeat for each option)Keep every SelectItem inside a SelectGroup. SelectLabel names a group of options; it does not label the trigger. Associate a FieldLabel with SelectTrigger's id. SelectContent handles its portal and scrolling internally. Use asChild for Radix parts that support custom element composition.
The trigger chevron rotates 180° while the popup is open, with a 150ms transition. Reduced-motion preferences disable the transition.
Sizes
Opened when you sign in.
Opened when you sign in.
Opened when you sign in.
controlSize | Height | Radius | Text |
|---|---|---|---|
sm | 24px | 3px | 12px / 16px |
default | 32px | 4px | 14px / 20px |
lg | 44px | 6px | 14px / 20px |
Set controlSize on SelectTrigger. Shared control tokens have fallbacks for installations without the theme. Use the large size for touch-oriented forms. Triggers fill their container; constrain the Field or preview layout for shorter values. Long selected labels truncate while menu options can wrap.
<SelectTrigger controlSize="sm" aria-label="Workspace">
<SelectValue placeholder="Choose a workspace" />
</SelectTrigger>Positioning and scrolling
The popup is portaled to the document body. By default, it opens at the trigger edge (position="popper", align="start"), with a 4px offset and 8px viewport collision padding. Use position="item-aligned" to align the selected option over the trigger. Scroll buttons and Radix keyboard navigation support longer lists; you can constrain the popup height with layout classes.
<SelectContent className="max-h-64" position="popper" align="start">
<SelectGroup>{/* SelectItem options */}</SelectGroup>
</SelectContent>Disabled and invalid
Opened when you sign in.
Opened when you sign in.
Disable the whole control on Select, or an individual SelectItem. For validation, mark Field with data-invalid, SelectTrigger with aria-invalid, and link the error with aria-describedby. Labels remain neutral. Hover emphasizes the trigger border; focus uses Migoy's solid 2px offset outline. Disabled controls cannot open the menu.
<Field data-invalid>
<FieldLabel htmlFor="required-workspace">Default workspace</FieldLabel>
<Select name="workspace" required>
<SelectTrigger id="required-workspace" aria-invalid aria-describedby="workspace-error">
<SelectValue placeholder="Choose a workspace" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectItem value="design">Design</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
<FieldError id="workspace-error">Choose a workspace.</FieldError>
</Field>Import Field, FieldLabel, and FieldError from your installed Field module for this composition.
Forms and accessibility
Associate a visible FieldLabel with the trigger ID. Put name, required, and disabled on Select for its form integration. A form submission includes the selected value under that name; disabled selects are omitted. Check submitted values against your allowed options on the server. For custom validation, validate the selected value explicitly and focus the trigger when invalid.
Tab focuses the trigger. Space, Enter, or Arrow Down opens the menu. Arrow keys move through enabled options; typing finds matching labels. Enter or Space selects, and Escape dismisses and restores trigger focus. Group labels give structure without becoming selectable values. See the settings form for a complete composition.
Based on shadcn Radix Select and Radix Select.