ComponentsForm
Select
An accessible dropdown select for choosing from a list of options. Built on Radix UI.
Default
Small Size
Disabled
Portal Container
SelectContent portals into document.body by default. A theme scoped to a class on a wrapper never reaches the body, so the open menu would read the page's theme instead. Pass the wrapper as container and the menu mounts inside it, under the scoped theme.
const [themeRoot, setThemeRoot] = React.useState<HTMLDivElement | null>(null);
<div ref={setThemeRoot} className="my-scoped-theme">
<Select>
<SelectTrigger>
<SelectValue placeholder="Pick one" />
</SelectTrigger>
<SelectContent container={themeRoot}>
<SelectItem value="a">Option A</SelectItem>
<SelectItem value="b">Option B</SelectItem>
</SelectContent>
</Select>
</div>Installation
npx visor add selectThis copies two files into your project:
components/ui/select/select.tsx— the componentcomponents/ui/select/select.module.css— the styles
Usage
import {
Select, SelectTrigger, SelectValue,
SelectContent, SelectItem,
} from '@/components/ui/select/select';
<Select>
<SelectTrigger>
<SelectValue placeholder="Pick one" />
</SelectTrigger>
<SelectContent>
<SelectItem value="a">Option A</SelectItem>
<SelectItem value="b">Option B</SelectItem>
</SelectContent>
</Select>API Reference
SelectProps
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | — | Controlled value of the selected item. |
defaultValue | string | — | Default selected value for uncontrolled usage. |
onValueChange | (value: string) => void | — | Callback when the selected value changes. |
disabled | boolean | false | Disables the select. |
size | 'sm' | 'md' | 'lg' | 'md' | Size of the select trigger (on SelectTrigger). |
position | 'popper' | 'item-aligned' | 'popper' | Positioning mode of the dropdown content (on SelectContent). |
Sub-components
| Component | Element | Purpose |
|---|---|---|
Select | — (Radix Root) | Root provider managing open state and value |
SelectTrigger | <button> | Clickable trigger that opens the dropdown |
SelectValue | <span> | Displays the selected value or placeholder text |
SelectContent | <div> (portal) | Dropdown panel containing options. Portals into document.body unless container is set |
SelectItem | <div> | Individual selectable option with check indicator |
SelectGroup | <div> | Groups related options together |
SelectLabel | <div> | Non-interactive label for an option group |
SelectSeparator | <div> | Visual divider between groups or items |
SelectScrollUpButton | <div> | Scroll-up indicator at the top of a long list |
SelectScrollDownButton | <div> | Scroll-down indicator at the bottom of a long list |
Accessibility
- Built on
@radix-ui/react-selectwith full WAI-ARIA combobox semantics - Trigger has
role="combobox"witharia-expandedandaria-haspopup="listbox" - Content renders a
role="listbox"; each item hasrole="option"witharia-selected - Always pair
SelectTriggerwith a<Label>viahtmlFor/idfor screen reader association - Keyboard: Space/Enter opens the dropdown; Arrow keys navigate options; Enter selects; Escape closes
Label Centering
The label is optically centred in any font: its line box is trimmed to the capital-height band, so capitals (not the font's ascent and descent) sit on the box centre, with the box size unchanged. Firefox keeps the previous rendering. Shared spec: docs/label-centering.md.