Select
Select is a form control for choosing a single value from a dropdown list. It features an accessible implementation with keyboard navigation and screen reader support, and also supports native form submission.
Playground
<Select>
<Select.Trigger>
<Select.Value placeholder="Select a fruit" />
</Select.Trigger>
<Select.Content>
<Select.Item value="apple">Apple</Select.Item>
<Select.Item value="banana">Banana</Select.Item>
<Select.Item value="cherry">Cherry</Select.Item>
<Select.Item value="grape">Grape</Select.Item>
</Select.Content>
</Select>Variants
Sizes
xssmdefaultlgxl| Size | Height | Font | Item | Preview |
|---|---|---|---|---|
xs | 36px | 13px | sm | |
sm | 40px | 14px | sm | |
default | 44px | 16px | md | |
lg | 48px | 16px | md | |
xl | 56px | 16px | lg |
API
Component Structure
Select— Radix Select.TriggerPropsTrigger button.ValueSelected value display.ContentPropsDropdown panel (flush support).ItemPropsSelection item.GroupItem group.LabelGroup label.SeparatorDividerProps
Select (Root)
size"default""xs" | "sm" | "default" | "lg" | "xl"Trigger height and font size. Auto-propagates to Content
radius"default""none" | "sm" | "base" | "default" | "lg" | "xl" | "2xl" | "3xl" | "full"Border radius size (6px). Applied directly to Trigger, auto-mapped to Content
valueundefinedstringSelected value for controlled mode
defaultValueundefinedstringInitial value for uncontrolled mode
onValueChangeundefined(value: string) => voidCallback when value changes
nameundefinedstringName for form submission
requiredundefinedbooleanMark as required field
disabledundefinedbooleanDisable the entire select
openundefinedbooleanOpen state for controlled mode
onOpenChangeundefined(open: boolean) => voidCallback when open state changes
| Name | Type | Default | Description |
|---|---|---|---|
size | "xs" | "sm" | "default" | "lg" | "xl" | "default" | Trigger height and font size. Auto-propagates to Content |
radius | "none" | "sm" | "base" | "default" | "lg" | "xl" | "2xl" | "3xl" | "full" | "default" | Border radius size (6px). Applied directly to Trigger, auto-mapped to Content |
value | string | undefined | Selected value for controlled mode |
defaultValue | string | undefined | Initial value for uncontrolled mode |
onValueChange | (value: string) => void | undefined | Callback when value changes |
name | string | undefined | Name for form submission |
required | boolean | undefined | Mark as required field |
disabled | boolean | undefined | Disable the entire select |
open | boolean | undefined | Open state for controlled mode |
onOpenChange | (open: boolean) => void | undefined | Callback when open state changes |
Select.Trigger
disabledundefinedbooleanDisable the trigger button
asChildfalsebooleanRender child element as trigger
| Name | Type | Default | Description |
|---|---|---|---|
disabled | boolean | undefined | Disable the trigger button |
asChild | boolean | false | Render child element as trigger |
Select.Content
position"popper""item-aligned" | "popper"Dropdown positioning method
flushfalsebooleanDisplay items full-width (no padding)
side"bottom""top" | "right" | "bottom" | "left"Dropdown display direction (popper only)
sideOffset1numberDistance from trigger (px)
| Name | Type | Default | Description |
|---|---|---|---|
position | "item-aligned" | "popper" | "popper" | Dropdown positioning method |
flush | boolean | false | Display items full-width (no padding) |
side | "top" | "right" | "bottom" | "left" | "bottom" | Dropdown display direction (popper only) |
sideOffset | number | 1 | Distance from trigger (px) |
Select.Item
value—stringItem value (required)
disabledundefinedbooleanMake item unselectable
textValueundefinedstringText value for typeahead
| Name | Type | Default | Description |
|---|---|---|---|
value | string | — | Item value (required) |
disabled | boolean | undefined | Make item unselectable |
textValue | string | undefined | Text value for typeahead |
Customization
classNameto customize the style of triggers and content.
Change width
<Select.Content className="w-72">Full-width trigger
<Select.Trigger className="w-full">Tip: Each sub-component accepts className, allowing you to override styles with Tailwind classes.
Anatomy
Best Practices
Recommended
- ✓Use when there are 5 or more options
- ✓Use Group to classify when there are many options
- ✓Guide selection with placeholder
- ✓Set name and required in forms
Avoid
- ✗Consider Radio for 3 or fewer options
- ✗Use Dropdown for executing actions
- ✗Consider alternative UI for multi-select needs
- ✗Don't leave both placeholder and initial value empty
Accessibility
Keyboard
ARIA Attributes
role="listbox"Auto-applied to Contentrole="option"Auto-applied to Itemaria-expandedTrigger state management- Character search via typeahead
Select vs Dropdown
They look similar but serve different purposes. Choose the right component for your use case.
Purpose
Select: Value selection
Dropdown: Action execution
Form integration
Select: name / value submission
Dropdown: None
After selection
Select: Value reflected in trigger
Dropdown: Menu just closes
Item types
Select: Single selection items
Dropdown: Item, Checkbox, Radio, Sub
Use cases
Select: Country, category, sort order
Dropdown: Context menu, account actions
| Feature | Select | Dropdown |
|---|---|---|
| Purpose | Value selection | Action execution |
| Form integration | name / value submission | None |
| After selection | Value reflected in trigger | Menu just closes |
| Item types | Single selection items | Item, Checkbox, Radio, Sub |
| Use cases | Country, category, sort order | Context menu, account actions |
Selection guide: Select is appropriate when users choose a value to submit in a form. When clicking triggers an action (edit, delete, share, etc.), use Dropdown instead.