Combobox

Searchable single-select input. Composes Popover + Command (cmdk) + a styled trigger. Pass a list of { value, label } options.

Default

Pre-selected

Disabled

Installation

pnpm
pnpm dlx @hex-core/cli add combobox

API Reference

PropTypeDefaultDescription
optionsrequired
objectArray of { value: string, label: string, disabled?: boolean }
value
stringControlled selected option value
onChange
functionCallback when the user picks an option: (value: string) => void
placeholder
stringSelect…Text shown on the trigger when nothing is selected
searchPlaceholder
stringSearch…Placeholder for the filter input
emptyText
stringNo results found.Shown inside the list when the search has no matches
disabled
booleanfalseDisable the trigger
aria-label
stringAccessible label — required when no adjacent visible <label> is used

AI Guidance

When to use

Use for a select input when the list is >~8 items or users benefit from typing to narrow. Fuzzy search + keyboard nav + selected-item checkmark.

When not to use

Don't use for native-select parity on mobile (use Select). Don't use for multi-select (this component is single-value — compose Command + Popover yourself for multi). Don't use for free-text entry (use Input).

Common mistakes

  • Passing duplicate option values (breaks selection and filtering)
  • Two options with identical labels — cmdk dedupes by the Item's filter value (the label here), so one will be dropped from the list
  • Using the label as the value — fine if stable, but prefer a short stable `value` string
  • Forgetting to bind value + onChange — uncontrolled mode doesn't exist on this wrapper
  • Mixing translated labels without keying on value — label changes won't update selection
  • Missing aria-label when there's no adjacent visible <label>

Accessibility

Trigger has role='combobox' + aria-expanded. Popover traps focus inside the CommandInput. Options are announced via cmdk's aria-activedescendant wiring.

Related components

Token budget: 900