Skip to content

Select

Choose one option from a list of up to about 15. Never submits on change.

  • Free core, MIT
  • Version 2.0.0-rc.1
  • APG pattern: Select-only combobox

Examples

These are the real React components. Use them with a mouse, touch or keyboard, and switch the theme and density for every example at once.

Default

Role
Show the code

Default, code

const roles = ['Owner', 'Admin', 'Member', 'Viewer'];

<Select defaultValue="Member" label="Role">
  {roles.map((r) => <SelectItem key={r} id={r}>{r}</SelectItem>)}
</Select>

Placeholder

RoleAdmins can invite and remove people.
Show the code

Placeholder, code

const roles = ['Owner', 'Admin', 'Member', 'Viewer'];

<Select placeholder="Choose a role" hint="Admins can invite and remove people." label="Role">
  {roles.map((r) => <SelectItem key={r} id={r}>{r}</SelectItem>)}
</Select>

Invalid

RoleError: Choose a role for this person
Show the code

Invalid, code

const roles = ['Owner', 'Admin', 'Member', 'Viewer'];

<Select placeholder="Choose a role" isRequired isInvalid errorMessage="Choose a role for this person" label="Role">
  {roles.map((r) => <SelectItem key={r} id={r}>{r}</SelectItem>)}
</Select>

Disabled

Role
Show the code

Disabled, code

const roles = ['Owner', 'Admin', 'Member', 'Viewer'];

<Select defaultValue="Owner" isDisabled label="Role">
  {roles.map((r) => <SelectItem key={r} id={r}>{r}</SelectItem>)}
</Select>

Open

Role
Show the code

Open, code

const roles = ['Owner', 'Admin', 'Member', 'Viewer'];

<Select defaultValue="Member" defaultOpen label="Role">
  {roles.map((r) => <SelectItem key={r} id={r}>{r}</SelectItem>)}
</Select>

Tokens

The 30 design tokens Select reads, with the value each has in the theme and density chosen above. Change a token and the component follows, in Figma and in code.

Show all 30 tokens
Tokens Select reads
TokenValue nowCSS variable
color.border.subtle…--sd-color-border-subtle
color.text.disabled…--sd-color-text-disabled
color.text.secondary…--sd-color-text-secondary
elevation.2…--sd-elevation-2
input.bg…--sd-input-bg
input.bg-disabled…--sd-input-bg-disabled
input.border…--sd-input-border
input.border-hover…--sd-input-border-hover
input.border-invalid…--sd-input-border-invalid
input.fg…--sd-input-fg
input.height…--sd-input-height
input.padding-x…--sd-input-padding-x
input.placeholder…--sd-input-placeholder
input.radius…--sd-input-radius
layer.dropdown…--sd-layer-dropdown
listbox.bg…--sd-listbox-bg
listbox.border…--sd-listbox-border
listbox.check…--sd-listbox-check
listbox.option-fg…--sd-listbox-option-fg
listbox.option-height…--sd-listbox-option-height
listbox.option-hover…--sd-listbox-option-hover
listbox.option-selected…--sd-listbox-option-selected
listbox.padding…--sd-listbox-padding
listbox.radius…--sd-listbox-radius
motion.duration.fast…--sd-motion-duration-fast
motion.easing.standard…--sd-motion-easing-standard
radius.sm…--sd-radius-sm
select.chevron…--sd-select-chevron
spacing.gap.sm…--sd-spacing-gap-sm
spacing.inset.md…--sd-spacing-inset-md

Install

The npm package isn’t published yet. When it is, this is the install line; until then, this page runs the same build of the package (from commit fa3abf8).

Install

npm i @superduperui/react @superduperui/tokens

Import

import { Select, SelectItem } from "@superduperui/react"

Props

Select also takes the props of the React Aria component it’s built on.

Select props
PropTypeWhat it does
labelrequiredstringVisible label (required).
hintstring
errorMessagestring | ((validation: ValidationResult) => string)
itemsIterable<T>Options as data; pair with a render function child.
childrenrequiredReactNode | ((item: T) => ReactNode)SelectItem elements, or a render function for `items`.
hideLabelbooleanKeep the label for assistive technology but hide it visually (e.g. a role select in a member row under a "Role" column label).

When to use it

Use it for

  • A short, known list (role, country with type-ahead)

Use something else for

  • Long or searchable lists: use Combobox (Tier 2)
  • 2 to 4 visible choices: use RadioGroup (Tier 2)
  • Actions: use Menu (Tier 2)

Accessibility

Screen readers announce "Role, Member, button, collapsed" then "Viewer, 4 of 4".

WCAG 2.2 AAA criteria the component meets in Comfortable density: 1.4.6, 1.4.9, 2.1.3, 2.3.2, 2.4.13, 2.5.5, 2.5.6, 2.3.3.

Compact density meets AA (2.5.8, 24px targets), not AAA.

What your product still has to do

  • Do not submit or navigate on selection

Shared patterns it ships with: 3.2.5 (no auto-submit).

This release’s test results

Test results for Select in this release
axe-core (WCAG A, AA, AAA and best practice)120 runs across every story, theme, density and width: 0 violations
Rendered text contrast225 text runs: 0 below 7:1, lowest 8.43:1
Target size36 targets: 0 under 44px in Comfortable
Focus appearance (2.4.13)63 focus stops in 3 browser engines: all pass
Keyboard scriptChromium 9 of 9, Firefox 9 of 9, WebKit 9 of 9

Manual passes with VoiceOver and NVDA haven’t been done yet.

Keyboard

Each step is scripted and run in Chromium, Firefox and WebKit.

Select keyboard steps
KeyWhat happens
TabTab reaches the trigger
EnterEnter opens the list on the selected option
ArrowDownDown moves to the next option
HomeHome moves to the first option
EndEnd moves to the last option
EnterEnter selects, closes and returns focus to the trigger
Alt+ArrowDownAlt+Down opens
Type-ahead moves to the first match
EscapeEsc closes without changing the value and returns focus

In Figma

The Figma component is Select, with State (Default, Hover, Focus, Open, Disabled, Invalid); Label visibility (Visible, Hidden). The Figma library isn’t published yet.

Figma to code: State (Default, Hover, Focus, Open, Disabled = isDisabled, Invalid = isInvalid); Label visibility → hideLabel (Visible = false, Hidden = true); Value → defaultValue (and the SelectItem); nested Label → label; nested Hint → hint; nested FieldError → errorMessage.