Inputs/Select

Select

Displays a list of options for the user to pick from.

Themed

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>

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.

PropTypeDefaultDescription
valuestringThe controlled value of the select.
defaultValuestringThe default value when initially rendered (uncontrolled).
onValueChange(value: string) => voidEvent handler called when the value changes.
openbooleanThe controlled open state of the select.
onOpenChange(open: boolean) => voidEvent handler called when the open state changes.
disabledbooleanfalseWhen true, prevents user interaction.
namestringThe name of the select for form submission.

SelectTrigger

The button that toggles the select dropdown.

PropTypeDefaultDescription
size"sm" | "default""default"The size of the trigger. Small triggers have a height of 32px.
classNamestringAdditional CSS classes for styling.
asChildbooleanfalseChange the default rendered element.

SelectContent

The dropdown panel that contains the selectable items.

PropTypeDefaultDescription
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.
sideOffsetnumber0The distance in pixels from the trigger.

SelectItem

An individual selectable option within the dropdown.

PropTypeDefaultDescription
valuestringThe value of the item (required).
disabledbooleanfalseWhen true, prevents user interaction with this item.
textValuestringOptional text for typeahead purposes. Defaults to the item text content.