Select
Displays a list of options for the user to pick from.
When to Use
Use Select when you need to:
- Present a list of 5 or more options that the user must pick from
- Save space compared to displaying all options inline as radio buttons
- Group related options into categorized sections with labels
- Provide a single-selection dropdown in a form
- Offer a custom-styled alternative to the native browser select
When Not to Use
- For fewer than 5 options where all fit on screen - use Radio Group
- When users need to search or filter through options - use Combobox
- For better native mobile UX with platform pickers - use Native Select
- For multi-selection scenarios - consider a checkbox list or multi-select combobox
Default
A select with grouped options and a placeholder.
Scrollable
Select with many grouped options that scroll. Scroll up and down buttons appear automatically when content overflows.
Disabled
Disabled select prevents all interaction and applies reduced opacity styling.
Controlled
Controlled select with external state management. The selected value is displayed below the select.
Selected: none
UX & Design Guidelines
Visual Hierarchy
The trigger uses border-input styling to match other form controls. The chevron icon provides a clear affordance that the element is expandable. Selected values display in text-foreground while placeholder text uses text-muted-foreground to differentiate empty from filled states.
Spacing & Layout
Set an explicit width on the trigger (e.g., w-[180px] or w-full) to prevent layout shifts when the selected value changes length. Use SelectGroup with SelectLabel to organize long lists into logical categories. Groups are visually separated and help users scan options faster.
Responsive Behavior
The dropdown content positions itself via Radix popper to stay within the viewport. On small screens, consider using w-full on the trigger so it spans the full container width. For mobile-heavy interfaces, consider Native Select which uses the platform picker for better touch interaction.
Color & Contrast
The dropdown uses bg-popover with text-popover-foreground for the content area. Focused items are highlighted with bg-accent and text-accent-foreground. Invalid states use border-destructive with a subtle ring to clearly communicate validation errors. All color combinations meet WCAG 2.1 AA contrast requirements.
Accessibility
Keyboard Navigation
- Tab — Move focus to the select trigger
- Enter or Space — Open the dropdown or select the focused item
- Arrow Down / Arrow Up — Navigate between options
- Escape — Close the dropdown without selecting
- Type a letter to jump to the first matching option (typeahead)
Screen Reader Support
- Built on Radix UI Select primitive with full WAI-ARIA listbox pattern
- Trigger announces its role as a combobox with the current value or placeholder
- Options announce their text content, position in the list, and selected state
- Group labels are announced as the user navigates into each section
- Disabled items are announced as unavailable
Focus Management
Visible focus ring with 3px width using focus-visible:ring-[3px]. When the dropdown opens, focus moves to the previously selected item or the first item. On close, focus returns to the trigger element. Focus is trapped within the dropdown while open.
ARIA Attributes
{/* Basic select with accessible label */}
<Select>
<SelectTrigger aria-label="Choose a fruit">
<SelectValue placeholder="Select a fruit" />
</SelectTrigger>
<SelectContent>
<SelectItem value="apple">Apple</SelectItem>
<SelectItem value="banana">Banana</SelectItem>
</SelectContent>
</Select>
{/* Select with external label */}
<Label htmlFor="country-select">Country</Label>
<Select>
<SelectTrigger id="country-select">
<SelectValue placeholder="Select a country" />
</SelectTrigger>
<SelectContent>
<SelectItem value="us">United States</SelectItem>
<SelectItem value="uk">United Kingdom</SelectItem>
</SelectContent>
</Select>
{/* Select with validation error */}
<Select aria-invalid="true">
<SelectTrigger aria-describedby="select-error">
<SelectValue placeholder="Select a role" />
</SelectTrigger>
<SelectContent>
<SelectItem value="admin">Admin</SelectItem>
<SelectItem value="user">User</SelectItem>
</SelectContent>
</Select>
<p id="select-error" className="text-sm text-destructive">
Please select a role.
</p>Related Components
API Reference
The Select component is composed of multiple sub-components. Below are the props for each.
Select
The root component that manages open state and value.
| Prop | Type | Default | Description |
|---|---|---|---|
| value | string | — | The controlled value of the select. |
| defaultValue | string | — | The default value when initially rendered (uncontrolled). |
| onValueChange | (value: string) => void | — | Event handler called when the value changes. |
| open | boolean | — | The controlled open state of the select. |
| onOpenChange | (open: boolean) => void | — | Event handler called when the open state changes. |
| disabled | boolean | false | When true, prevents user interaction. |
| name | string | — | The name of the select for form submission. |
SelectTrigger
The button that toggles the select dropdown.
| Prop | Type | Default | Description |
|---|---|---|---|
| size | "sm" | "default" | "default" | The size of the trigger. Small triggers have a height of 32px. |
| className | string | — | Additional CSS classes for styling. |
| asChild | boolean | false | Change the default rendered element. |
SelectContent
The dropdown panel that contains the selectable items.
| Prop | Type | Default | Description |
|---|---|---|---|
| position | "item-aligned" | "popper" | "popper" | The positioning mode for the content dropdown. |
| align | "start" | "center" | "end" | "center" | The horizontal alignment of the content relative to the trigger. |
| side | "top" | "right" | "bottom" | "left" | "bottom" | The preferred side of the trigger to render against. |
| sideOffset | number | 0 | The distance in pixels from the trigger. |
SelectItem
An individual selectable option within the dropdown.
| Prop | Type | Default | Description |
|---|---|---|---|
| value | string | — | The value of the item (required). |
| disabled | boolean | false | When true, prevents user interaction with this item. |
| textValue | string | — | Optional text for typeahead purposes. Defaults to the item text content. |