You're in the Library

Combobox

A text input that filters a list of options as the user types, then selects one or several of them. Built for long lists and async search (people, repositories, tokens).
Stable
Edit

Preview appears after the next Storybook update.

Combobox example
<Combobox />
Rendered with the real componentFrom the code
Light
Dark

When to use

Use it for

  • Choosing from a long or growing list where typing is faster than scrolling: reviewers, repositories, components, tokens.
  • Results come from a server: control inputValue, fetch, pass the results as options with filter={null} and loading while waiting.
  • Several values from a long list (multiple): selected values become removable chips inside the field.
  • Inside a Dialog or Drawer: the list opens above the dialog and focus stays in it. Use description for a short second line under each label (12px, muted), like a component's family or a person's role.

Not for

  • Short known lists (under about ten): use Select, which needs no typing.
  • Free text with suggestions (a search box): the value must be one of the options here, so use Input or an autocomplete pattern.
  • Two or three options: use RadioGroup.

Do and don't

Every example is rendered with the real component, so it always matches what ships.

Do

Add a second line when names are ambiguous

A role or an email under the name helps pick the right Ada, and is matched by screen readers too.

Do

Write an empty message that says what to try

"No one matches. Check the spelling or invite them." turns a dead end into a next step.

Don't

Spinner with no words

While loading, say what is happening ("Searching people"). The message is also announced to screen readers.

Don't

Combobox for a handful of fixed options

Typing to find one of three themes is slower than seeing them. Use Select or RadioGroup.

Accessibility

  • Base UI Combobox: the input has role combobox with aria-expanded, aria-controls and aria-activedescendant; the popup is a listbox.
  • Keyboard: typing filters; Down Arrow opens and moves; Enter selects; Escape closes, then clears; with multiple, Left Arrow from the start of the input moves through the chips and Backspace removes one.
  • loading renders the message in a live status region and sets aria-busy on the popup; the empty message is announced the same way.
  • The clear and toggle buttons inside the field have accessible names ("Clear selection", "Show options"); each chip remove button says "Remove <name>".
  • The Field label names the input; hint and error are linked through aria-describedby.
  • The popup is portaled and re-applies the theme, brand and density of its field. It sits on the popover layer, above a Dialog, and the dialog keeps focus management: picking returns focus to the input inside the dialog.

Content guidelines

  • Placeholder hints at what to type: "Search people", "Type a component name".
  • Empty message: say there is no match and what to try next, in one sentence.
  • Loading message is a present participle phrase: "Searching people", "Loading repositories".
  • Option labels are the names users know (people's display names, component names), not ids.

From the code Generated from the component, not editable here.

Anatomy and tokens

Read from packages/react/src/components/Combobox/Combobox.module.css at build time. Every value is a token: open one to see its alias chain in both themes.

51 tokens29 semantic or component, change with theme and brand6 density, change with comfortable or compact16 from the shared scales

Motion and interaction

Combobox animates on hover, open and close. Try it in the preview at the top.

PartWhenWhat changesDurationEasing
TriggerHoverBackground and bordermotion.duration.instant75 msmotion.easing.standardsettles in place
PopupOpenFade and movementmotion.duration.fast150 msmotion.easing.enterstarts fast, lands softly
PopupCloseFade and movementmotion.duration.fast150 msmotion.easing.exitstarts softly, leaves fast

With reduced motion turned on, every change happens at once.

From the code Generated from the component, not editable here.

Props

Parsed from the TypeScript types in packages/react/src/components/Combobox/Combobox.tsx, so this table cannot drift from the code. It also accepts every native <input> attribute except value, defaultValue, onChange, size, prefix, children.

PropTypeDefaultDescription
optionsrequiredComboboxOption[]noneThe options to filter. For async search, pass the latest results and set `filter={null}`.
multiplebooleanfalsePick several values, shown as removable chips.
valueComboboxValuenoneSelected value (controlled): a string, an array with `multiple`, or null.
defaultValueComboboxValuenoneInitially selected value (uncontrolled).
onValueChange(value: ComboboxValue) => voidnoneCalled with the new value (string, string[] with `multiple`, or null).
inputValuestringnoneText in the input (controlled). Use it to drive an async search.
defaultInputValuestringnoneNo description in the code yet.
onInputValueChange(inputValue: string) => voidnoneCalled on every keystroke with the query.
filter((option: ComboboxOption, query: string) => boolean) | nullnoneCustom matcher, or `null` to show `options` as given (already filtered by a server). Default: case and accent insensitive "contains".
loadingbooleanfalseResults are loading: shows a spinner row, sets aria-busy and announces `loadingMessage`.
loadingMessagestring'Loading results'Announced and shown while loading. Default "Loading results".
emptyMessageReactNode'No matches. Try another name.'Shown when no option matches. Say what to try next.
labelstringnoneVisible label. When set, the Combobox wraps itself in a Field. Leave unset inside a Field.
hintReactNodenoneHelp under the label (Field description). Only with `label`.
errorReactNodenoneError message. Only with `label`.
hideLabelbooleannoneNo description in the code yet.
size'sm' | 'md' | 'lg''md'Height follows the density tokens. Default `md`.
prefixReactNodenoneContent before the query, usually a search Icon.
openbooleannonePopup open state (controlled).
defaultOpenbooleannoneNo description in the code yet.
onOpenChange(open: boolean) => voidnoneNo description in the code yet.
portalContainerHTMLElement | ShadowRoot | RefObject<HTMLElement | ShadowRoot | null> | nullnoneWhere the popup is rendered. Default: the end of the body, above every layer including a Dialog or Drawer, so the list is never covered. Pass an element (or a ref) to keep it inside a container, for example a shadow root.

Playground

Change the props and see the real Combobox update. Controls are generated from the TypeScript props; nothing here changes the system.

Code for these props
<Combobox label="Reviewer" placeholder="Search people" />

size

Workbench

For contributors: every state with the accessibility panel, in the component workbench (Storybook). The stories double as visual test fixtures; the guidance on this page is the user documentation (open Combobox in Storybook).

Embed Storybook stories here (9)

Loads from https://bridge-storybook.floriangouloubi.com (set STORYBOOK_URL at build time). If Storybook is not running, the frames stay empty.

Default

InsideDialog

Grouped

Multiple

WithError

Open

AsyncSearch

Loading

AllStates

From the code Generated from the component, not editable here.

Changelog

  • New

    The measure now writes the Figma sets drawn under a component's folder as their own entries, so Claude can fix them: popups drawn open (Dialog/Popup, AlertDialog/Popup, Drawer/Popup, Menu/Popup, Popover/Popup, Tooltip/Popup, and Select/Popup or Combobox/Popup, measured open when the stories show them closed) and sets that fix a prop (Pagination/Full, Pagination/Compact, Progress/Linear)

    v1.0.0, Nov 11, 2026

  • Fix

    Component specs count height and width as the content box (a bordered table cell is its height plus its border), the Figma build draws an empty sized slot at its padding instead of 100px, and stories reach every Figma variant: a disabled control on IconButton, Input, Select, Combobox and Textarea, and Figma variant stories for AccordionItem, MenuItem, MenuCheckboxItem, MenuSubmenu and TableEmpty

    v1.0.0, Nov 11, 2026

  • Fix

    Select and Combobox: the highlighted option's corners now follow the popup's corners, like Menu items

    v1.0.0, Nov 11, 2026

  • Fix

    Combobox: a chip cut by the field width shows its full value on hover (title)

    v1.0.0, Nov 11, 2026

  • Fix

    Combobox: the listbox takes the field's name (its label, aria-label or aria-labelledby), so it is never an anonymous list, including while it closes

    v1.0.0, Nov 11, 2026

All release notes