Combobox
A composable searchable selection primitive with filtering, keyboard navigation, and single or multi-select modes.
Features
- Single or multi-select
- Built-in filtering
- Controlled or uncontrolled
- Grouped options
- Multi-select tags
- Headless styling
Installation
npm install @ariaui/combobox
Examples
Three layouts from the legacy docs: grouped single-select (fruits and animals), a GitHub-style user picker with avatar chips, and a multi-select with removable tags and grouped checkbox rows.
Styling uses semantic tokens via shared class strings in comboboxExampleTokens.ts; icons are from @heroicons/react/24/outline.
Grouped options
Single selection with two labeled groups and a divider. Typeahead filters options.
No preview output yet.
Framer Motion
Grouped combobox content animated through Framer Motion with Content asChild.
No preview output yet.
User selector
Selected value shown as a chip with avatar; list rows show the same avatar and a check when active.
No preview output yet.
Multi-select
Multiple selection with tags, overflow count, removable chips, and grouped options with checkbox-style indicators.
No preview output yet.
Multi-select (Advanced)
Advanced multi-select with removable tags, overflow count, and grouped option sections.
No preview output yet.
Anatomy
import * as Combobox from "@ariaui/combobox";
export default function Example() {
return (
<Combobox.Root>
<Combobox.Trigger>
<Combobox.TagGroup>
<Combobox.Tag />
</Combobox.TagGroup>
<Combobox.Input />
<Combobox.Button />
</Combobox.Trigger>
<Combobox.Content>
<Combobox.Group>
<Combobox.Label />
<Combobox.Option />
</Combobox.Group>
</Combobox.Content>
</Combobox.Root>
);
}
API Reference
Root
State container. Owns selected value, input text, open state, and positioning references.
| Prop | Type | Default |
|---|---|---|
value | string | string[] | — |
defaultValue | string | string[] | — |
onValueChange | (value: string | string[]) => void | — |
inputValue | string | — |
defaultInputValue | string | "" |
onInputValueChange | (value: string) => void | — |
open | boolean | — |
defaultOpen | boolean | false |
onOpenChange | (open: boolean) => void | — |
selectionMode | "single" | "multiple" | "single" |
offset | { x: number; y: number } | — |
disabled | boolean | false |
Trigger
Wrapper for Input and Button. Carries `role="combobox"` and the open-state ARIA attributes. Acts as the positioning anchor for the popup.
| Attribute | Values |
|---|---|
| role | combobox |
| aria-haspopup | listbox |
| aria-expanded | true | false |
| aria-controls | ID of the Content listbox (when open) |
| aria-disabled | true (when disabled) |
Input
Filter textbox. Opens the listbox on typing or mouse down and forwards navigation keys to the popup.
| Prop | Type | Default |
|---|---|---|
placeholder | string | — |
| Attribute | Values |
|---|---|
| aria-autocomplete | list |
| aria-activedescendant | ID of the active option |
Content
Popup listbox rendered through a portal. Owns active-item tracking, visible-option filtering, and keyboard navigation.
| Prop | Type | Default |
|---|---|---|
fallback | React.ReactNode | — |
asChild | boolean | false |
| Attribute | Values |
|---|---|
| role | listbox |
| aria-labelledby | ID of the associated trigger |
| aria-multiselectable | true (in multi-select mode) |
Group
Groups related options. Hides itself when none of its child options match the current filter.
| Attribute | Values |
|---|---|
| role | group |
| aria-labelledby | ID of the associated Label |
Label
Label for a Group. Provides the `aria-labelledby` target.
Option
Selectable listbox option. Filters itself from view based on the current input text using case-insensitive prefix matching.
| Prop | Type | Default |
|---|---|---|
value* | string | — |
disabled | boolean | false |
| Attribute | Values |
|---|---|
| role | option |
| aria-selected | true | false |
| [data-value] | The option value string |
| [data-active] | true (when keyboard-highlighted) |
| [data-state] | checked | unchecked |
| [data-disabled] | Present when disabled |
TagGroup
Optional overflow-aware container for multi-select tags inside Trigger.
Tag
Passive visual tag for a selected value in multi-select mode. Does not provide built-in removal controls.
Keyboard
| Shortcut | Action |
|---|---|
| ↓ | Open the popup if closed, or move to the next option. |
| ↑ | Open the popup if closed, or move to the previous option. |
| Home | Move to the first enabled option. |
| End | Move to the last enabled option. |
| Enter | Select the active option. |
| Esc | Close the popup. |
| Backspace | In multi-select mode with an empty input, remove the last selected value. |
Accessibility
The Combobox component implements the WAI-ARIA Combobox pattern:
Triggercarriesrole="combobox"witharia-haspopup="listbox"andaria-expanded.Inputexposesaria-autocomplete="list"and tracks the active option viaaria-activedescendant.Contentrenders asrole="listbox"witharia-multiselectablein multi-select mode.- Each
Optionexposesrole="option"witharia-selectedreflecting its checked state. - Focus stays on the input during keyboard navigation; the active option is communicated via
aria-activedescendant.
Label your groups
Always provide aria-label or aria-labelledby on Combobox.Group containers to give screen-reader users context about grouped options.