Skip to main content

Combobox

Searchable dropdown that combines a typeahead filter with full keyboard navigation. Supports grouped options, single or multi-select, controlled and uncontrolled patterns, and complete WAI-ARIA combobox semantics.

Live Preview

Try the Combobox in real time. Toggle size, validation state, multi-select, and disabled to see how the trigger and panel adapt.

tsx
1<Combobox2  value={value}3  onChange={setValue}4  options={frameworks}5  size="md"6  state="default"7  label="Framework"8  placeholder="Choose a framework"9/>

Installation

Install the Aidash Components package using your preferred package manager.

$ pnpm add @aidash/components

Import

Import the Combobox component into your file.

tsx
import { Combobox } from '@/components/aidash/combobox';

Basic Usage

Single-select Combobox with a small option list. Type in the filter box to narrow results.

tsx
1const [value, setValue] = useState('');2 3<Combobox4  value={value}5  onChange={setValue}6  options={[7    { value: 'apple', label: 'Apple' },8    { value: 'banana', label: 'Banana' },9    { value: 'cherry', label: 'Cherry' },10    { value: 'durian', label: 'Durian' },11  ]}12  placeholder="Pick a fruit"13/>

Multi Select

Enable multiple selections. Selected labels appear as chips inside the trigger and the panel stays open while toggling.

tsx
1const [value, setValue] = useState<string[]>(['react', 'svelte']);2 3<Combobox4  multiple5  value={value}6  onChange={setValue}7  options={frameworks}8  placeholder="Pick frameworks"9  label="Favorites"10/>

Grouped Options

Assign a group to each option. The panel renders each group with a small uppercase header, and headers disappear automatically when the filter empties a group.

tsx
1const options: ComboboxOption[] = [2  { value: 'react', label: 'React', group: 'Libraries' },3  { value: 'vue', label: 'Vue', group: 'Libraries' },4  { value: 'preact', label: 'Preact', group: 'Libraries' },5  { value: 'nextjs', label: 'Next.js', group: 'Frameworks' },6  { value: 'nuxt', label: 'Nuxt', group: 'Frameworks' },7  { value: 'sveltekit', label: 'SvelteKit', group: 'Frameworks' },8  { value: 'astro', label: 'Astro', group: 'Frameworks' },9];10 11<Combobox12  value={value}13  onChange={setValue}14  options={options}15  placeholder="Pick a tool"16  label="Stack"17/>

Sizes

Three sizes matching the Select scale: sm, md, lg.

tsx
1<Combobox size="sm" options={frameworks} placeholder="Small" />2<Combobox size="md" options={frameworks} placeholder="Medium" />3<Combobox size="lg" options={frameworks} placeholder="Large" />

Validation States

Reflect validation results in the trigger border and helper text.

Pick any option

Looks good

Double-check this choice

Selection is required

tsx
1<Combobox state="default" options={frameworks} helperText="Pick any option" />2<Combobox state="success" options={frameworks} helperText="Looks good" value="react" />3<Combobox state="warning" options={frameworks} helperText="Double-check this choice" value="qwik" />4<Combobox state="error" options={frameworks} helperText="Selection is required" />

Disabled State

Disabled Comboboxes are dimmed, unfocusable, and cannot be opened.

tsx
1<Combobox disabled options={frameworks} value="react" label="Framework" />

Accessibility

Built following the WAI-ARIA combobox pattern.

role="combobox"

The trigger exposes role="combobox", aria-expanded, aria-haspopup="listbox", and aria-controls.

aria-activedescendant

The filter input tracks the highlighted option via aria-activedescendant, so screen readers announce each result as it becomes active.

Keyboard Navigation

Down / Enter / Space opens the panel. Once open, Up / Down move the highlight, Home / End jump to the ends, Enter selects (single) or toggles (multi), Escape closes, and Tab dismisses without changing selection.

Focus Management

When the panel closes via Escape or selection in single mode, focus returns to the trigger button so keyboard users never lose their place.

tsx
1<Combobox2  label="Framework"3  value={value}4  onChange={setValue}5  options={frameworks}6/>7{/* Renders: <button role="combobox" aria-expanded aria-haspopup="listbox" aria-controls> */}

API Reference

Complete list of props for the Combobox component and its option shape.

ComboboxProps
PropTypeDefaultDescription
optionsComboboxOption[]Array of options to display, each with a value and label.
valuestring | string[]Selected value(s). Use a string for single mode, string[] for multi.
onChange(value: string | string[]) => voidFired when the selection changes.
multiplebooleanfalseEnable multi-select mode. Value becomes string[].
placeholderstring'Select…'Trigger placeholder when nothing is selected.
searchPlaceholderstring'Search…'Placeholder text inside the filter input.
emptyMessagestring'No results.'Message shown when the filter has no matches.
size'sm' | 'md' | 'lg''md'Trigger height and padding.
state'default' | 'success' | 'warning' | 'error''default'Border color reflecting validation state.
disabledbooleanfalseDisable interaction and dim the trigger.
labelstringText label rendered above the trigger.
helperTextstringHelper text rendered below the trigger.
idstringautoDOM id for the trigger. Auto-generated when omitted.
classNamestring''Additional CSS classes on the wrapper.
ComboboxOption
PropTypeDefaultDescription
valuestringUnique identifier for the option.
labelstringDisplay text for the option.
descriptionstringOptional secondary text; also searchable.
disabledbooleanfalsePrevents the option from being selected.
groupstringGroup header this option belongs to.
Note
Combobox works in either controlled or uncontrolled fashion. Pass value and onChange for controlled mode, or omit them to let the parent skip storing state. For very large option lists (500+), consider building a virtualized variant on top of this component to keep the panel snappy.

Other components that work well alongside Combobox.