Skip to content
Redpanda UI
Esc
↑↓navigate↵open⌘Jpreview
Made by shadcn
Edit on GitHub

Select

Displays a list of options for the user to pick one from, opened by a button, with groups, separators and keyboard navigation.

Installation

bash
npx shadcn@latest add @redpanda/select
bash
pnpm dlx shadcn@latest add @redpanda/select
bash
yarn dlx shadcn@latest add @redpanda/select
bash
bunx shadcn@latest add @redpanda/select
bash
nubx shadcn@latest add @redpanda/select
bash
aube dlx shadcn@latest add @redpanda/select

When to use

Select components provide single-option selection from a list of options. Use this decision tree:

Usage

tsx
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
tsx
<Select>  <SelectTrigger className="w-[180px]">    <SelectValue placeholder="Theme" />  </SelectTrigger>  <SelectContent>    <SelectItem value="light">Light</SelectItem>    <SelectItem value="dark">Dark</SelectItem>    <SelectItem value="system">System</SelectItem>  </SelectContent></Select>

Anatomy

The Select component is built with Base UI primitives:

plaintext
<Select> (Root Container)├── <SelectTrigger> (Button)│   ├── <SelectValue> (Placeholder/Selected)│   └── <ChevronDown> Icon├── <SelectContent> (Dropdown)│   ├── Portal rendering│   ├── Positioning system│   └── <SelectItem> (Options)│       ├── Checkmark indicator│       └── Item text└── Keyboard/Mouse handling

Props

Resolving labels in the trigger

<SelectValue> accepts three forms for the trigger label, in order of preference:

  1. No children — the registry wrapper defers to Base UI’s native resolution. Pass an items map on <Select> to look up the label, otherwise the raw value is stringified.
  2. Static children — render the same node regardless of value (rarely useful for selects).
  3. Render-prop children — (value) => ReactNode. Returning null/undefined falls back to placeholder. Use this for rich trigger content (icon + label, avatar + name, status dot + label) that mirrors the selected item.
tsx
<Select items={{ '1': 'Any', '2': 'Read', '3': 'Write' }} value="1">  <SelectTrigger>    <SelectValue placeholder="Select operation" />  </SelectTrigger>  …</Select>
// or, for rich content:<SelectValue placeholder="Assign to teammate">  {(value) => {    const user = users.find((u) => u.value === value);    return user ? <UserContent user={user} /> : null; // null → placeholder  }}</SelectValue>

Examples

Scrollable

Groups

Disabled options

With description

With icon

Status indicator

Avatars

Custom rendering

Object values

Placeholder and clearable

Error state

Loading state

Enum-backed value (label ≠ String(value))

Form

Keyboard interactions

Key Action
Enter / Space / ArrowDown on SelectTrigger Opens the listbox and focuses the currently selected item (or the first if none).
ArrowUp / ArrowDown Moves between options.
Home / End Jumps to first / last option.
Enter Selects the focused option and closes the listbox.
Escape Closes without changing selection.
Typing a character Typeahead jumps to the next option whose label starts with that character.

Accessibility

  • SelectTrigger is a real button with aria-haspopup="listbox" and aria-expanded; the listbox carries role="listbox" and each item role="option" with aria-selected.
  • Provide a visible label via <Label htmlFor> or wrap the select in a <Field> so the selected value has a programmatic name.
  • onValueChange is typed (value: string, eventDetails) => void — Base UI’s two-argument signature with value narrowed to string.
  • For large option lists (>20), prefer Combobox so users can type-ahead-filter. Select’s typeahead only jumps to matching first letters.

Credits

  • We use Base UI for the select component.
  • We take our inspiration from Shadcn UI for the select style.

Recent changes

  • patchv1.2.0Pin shipped dependency floors to the version we develop against. Registry items now declare ranges like `^5.1.9` (the actual installed version) instead of collapsing to `^5.0.0`, so consumers start on the known-tested baseline while caret semantics still allow any compatible release within the same major.#133
  • minorv1.1.0Theme docs refresh, readability pass on semantic foregrounds, and consumer-facing Base UI regression fixes.#121
  • minorv1.0.0Post-Base-UI polish. Public API unchanged.#116
  • majorv1.0.0Migrate every Radix-based primitive to `@base-ui/react@^1.4.0` (Base UI).#114
  • patchv0.3.1## 🚧 Updated#112
See full history →

Last updated on

Was this page helpful?