Skip to content
Protocore Design Systemv1.6.9

/// Inputs

Select

Input-styled trigger plus an overlay panel for choosing one value from a list; flat or compound API.

import { Select } from "@protocore/pds";
View as Markdown

Basics

The one-prop form: pass options and Select renders the trigger and panel for you. Controllable via value / defaultValue / onValueChange.

Groups & separators

Drop to the compound API — Select.Root, Trigger, Content, Group, Label, Separator, Item — when you need captioned groups or custom item content.

In a Field, invalid

Set invalid for the danger border and aria-invalid. Pair with a Field error to announce the message. Trigger height follows size (sm · md · lg).

When to use it

Use Select for choosing one value from a known, moderate list (roughly 5–30 options) that doesn't need to stay on screen. When the list is short and worth showing in full, a RadioGroup saves a click; when it's just 2–4 modes, use SegmentedControl. When the list is long or benefits from type-ahead filtering, reach for Combobox instead. For selecting *many* values, use a multi-select FilterBar or a set of Checkboxes.

Usage

Do

  • Give the trigger an accessible name via a `Field` label or `aria-label`.
  • Provide a `placeholder` when there's no sensible default selection.
  • Use `Select.Group` + `Select.Label` to structure long option lists.
  • Keep option `value`s stable and non-empty — Radix disallows an empty string value.

Don't

  • Don't use Select when users need to filter by typing — use Combobox.
  • Don't cram 2–3 options into a Select — a SegmentedControl or RadioGroup reads faster.
  • Don't put interactive controls (buttons, links) inside a `Select.Item`.
  • Don't leave the trigger unlabelled when no visible field label wraps it.

Accessibility

KeysAction
Space / Enter / Arrow DownOpen the panel from the focused trigger.
Arrow Up / DownMove between options while open.
EnterSelect the highlighted option and close.
Type a letterJump to the next option starting with that character.
EscClose the panel without changing the value.
  • Built on Radix Select — the panel is portalled, focus is trapped while open, and focus returns to the trigger on close.
  • The trigger exposes `aria-expanded`; the active option carries `aria-selected` with a check indicator.
  • `invalid` sets `aria-invalid` on the trigger for assistive tech.

Select props

PropTypeDefaultDescription
aria-describedbystringIds of elements describing the trigger (e.g. a `<Field>` hint/error).
aria-labelstringAccessible label for the trigger when no visible `<Field>` label wraps it.
aria-labelledbystringIds of elements labelling the trigger (e.g. a `<Field>` label).
classNamestringClass applied to the trigger.
defaultValuestring
idstringId applied to the trigger button — wired automatically when wrapped in `<Field>`.
invalidbooleanMark the trigger invalid.
onValueChange((value: string) => void)
options *SelectOption[]Options to render; use the compound API instead for groups or custom item content.
placeholderReactNodePlaceholder shown when no value is selected.
sizeenummdTrigger height.
valuestring

SelectTrigger props

PropTypeDefaultDescription
asChildboolean
classNamestring
invalidbooleanMark the trigger invalid — danger border plus `aria-invalid`.
sizeenummdTrigger height: `sm` (32) · `md` (36, default) · `lg` (40).
styleCSSProperties

SelectItem props

PropTypeDefaultDescription
asChildboolean
classNamestring
styleCSSProperties

Related

  • ComboboxAutocomplete field — a sunken input that filters a list as you type, following the ARIA 1.2 combobox pattern.
  • RadioGroupOne-of-many selection with sharp square markers; the active option carries the accent fill.
  • SegmentedControlCompact single-select toggle — a bordered row of mono uppercase segments where the active one inverts to a solid fill.
  • FieldForm-field wrapper: a caption label, the control, and hint or error messaging with ARIA wired for you.