Skip to content

Combobox

A text input that filters a list as you type. For long or searchable lists; the number of matches is announced.

  • Free core, MIT
  • Version 2.0.0-rc.1
  • APG pattern: Combobox with listbox popup

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

Show the code

Default, code

const countries = ['Australia', 'Austria', 'Belgium', 'Canada', 'Denmark', 'Finland', 'France', 'Germany', 'Ireland', 'Italy', 'Netherlands', 'New Zealand', 'Norway', 'Portugal', 'Spain', 'Sweden', 'Switzerland', 'United Kingdom', 'United States'];

<Combobox placeholder="Start typing a country" label="Country">
  {countries.map((c) => <ComboboxItem key={c} id={c}>{c}</ComboboxItem>)}
</Combobox>

With a value

Where your company is registered.
Show the code

With a value, code

const countries = ['Australia', 'Austria', 'Belgium', 'Canada', 'Denmark', 'Finland', 'France', 'Germany', 'Ireland', 'Italy', 'Netherlands', 'New Zealand', 'Norway', 'Portugal', 'Spain', 'Sweden', 'Switzerland', 'United Kingdom', 'United States'];

<Combobox defaultSelectedKey="United Kingdom" hint="Where your company is registered." label="Country">
  {countries.map((c) => <ComboboxItem key={c} id={c}>{c}</ComboboxItem>)}
</Combobox>

Invalid

Error: Choose a country from the list
Show the code

Invalid, code

const countries = ['Australia', 'Austria', 'Belgium', 'Canada', 'Denmark', 'Finland', 'France', 'Germany', 'Ireland', 'Italy', 'Netherlands', 'New Zealand', 'Norway', 'Portugal', 'Spain', 'Sweden', 'Switzerland', 'United Kingdom', 'United States'];

<Combobox isRequired isInvalid errorMessage="Choose a country from the list" label="Country">
  {countries.map((c) => <ComboboxItem key={c} id={c}>{c}</ComboboxItem>)}
</Combobox>

Disabled

Show the code

Disabled, code

const countries = ['Australia', 'Austria', 'Belgium', 'Canada', 'Denmark', 'Finland', 'France', 'Germany', 'Ireland', 'Italy', 'Netherlands', 'New Zealand', 'Norway', 'Portugal', 'Spain', 'Sweden', 'Switzerland', 'United Kingdom', 'United States'];

<Combobox defaultSelectedKey="Ireland" isDisabled label="Country">
  {countries.map((c) => <ComboboxItem key={c} id={c}>{c}</ComboboxItem>)}
</Combobox>

With descriptions

Show the code

With descriptions, code

<Combobox label="Assign to" placeholder="Search people">
  <ComboboxItem id="priya" description="Design lead">Priya Shah</ComboboxItem>
  <ComboboxItem id="tom" description="Engineer">Tom Ellis</ComboboxItem>
  <ComboboxItem id="ana" description="Researcher">Ana Costa</ComboboxItem>
</Combobox>

Tokens

The 12 design tokens Combobox 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 12 tokens
Tokens Combobox reads
TokenValue nowCSS variable
color.bg.subtle…--sd-color-bg-subtle
color.text.secondary…--sd-color-text-secondary
input.height…--sd-input-height
input.radius…--sd-input-radius
listbox.check…--sd-listbox-check
listbox.option-selected…--sd-listbox-option-selected
listbox.padding…--sd-listbox-padding
motion.duration.fast…--sd-motion-duration-fast
select.chevron…--sd-select-chevron
spacing.inset.md…--sd-spacing-inset-md
spacing.inset.sm…--sd-spacing-inset-sm
target.min…--sd-target-min

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 { Combobox, ComboboxItem } from "@superduperui/react"

Props

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

Combobox props
PropTypeWhat it does
labelrequiredstringVisible label (required).
hintstring
errorMessagestring | ((validation: ValidationResult) => string)
placeholderstring
childrenrequiredReactNode | ((item: T) => ReactNode)ComboboxItem elements, or a render function for `items`.
hideLabelbooleanKeep the label for assistive technology but hide it visually.
emptyTextstringDefault 'No matches'Text shown when nothing matches. Default "No matches".

When to use it

Use it for

  • Long lists (countries, people, projects)
  • Lists people search by name rather than scan

Use something else for

  • Up to about 15 known options: use Select
  • 2 to 4 visible choices: use RadioGroup
  • Free text with suggestions you must accept: use TextField

Accessibility

Screen readers announce "Country, combobox, collapsed"; while typing "2 results"; on Down "Sweden, 1 of 2".

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

  • Keep option labels unique so type-to-filter finds one
  • Do not submit on selection

Shared patterns it ships with: 3.3.5 (hint and result count).

This release’s test results

Test results for Combobox 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 contrast145 text runs: 0 below 7:1, lowest 8.43:1
Target size56 targets: 0 under 44px in Comfortable
Focus appearance (2.4.13)18 focus stops in 3 browser engines: all pass
Keyboard scriptChromium 6 of 6, Firefox 6 of 6, WebKit 6 of 6

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

Keyboard

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

Combobox keyboard steps
KeyWhat happens
TabTab reaches the input
Typing filters the list and opens it
ArrowDownDown moves to the first match (focus stays in the input)
EnterEnter picks it and closes the list
ArrowDownDown reopens the list
EscapeEsc closes the list and keeps the value

In Figma

The Figma component is Combobox, with State (Default, Hover, Focus, Open, Disabled, Invalid); Label visibility (Visible, Hidden); Content (Placeholder, Value). 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); Content (Placeholder, Value; preview only); Value → defaultInputValue; Placeholder → placeholder; nested Label → label; nested Hint → hint; nested FieldError → errorMessage; nested ComboboxItem → children (the ComboboxItem options).