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.

Preview

No preview output yet.

live.tsxReady

Framer Motion

Grouped combobox content animated through Framer Motion with Content asChild.

Preview

No preview output yet.

live.tsxReady

User selector

Selected value shown as a chip with avatar; list rows show the same avatar and a check when active.

Preview

No preview output yet.

live.tsxReady

Multi-select

Multiple selection with tags, overflow count, removable chips, and grouped options with checkbox-style indicators.

Preview

No preview output yet.

live.tsxReady

Multi-select (Advanced)

Advanced multi-select with removable tags, overflow count, and grouped option sections.

Preview

No preview output yet.

live.tsxReady

Anatomy

tsx
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.

PropTypeDefault
value
string | string[]
defaultValue
string | string[]
onValueChange
(value: string | string[]) => void
inputValue
string
defaultInputValue
string""
onInputValueChange
(value: string) => void
open
boolean
defaultOpen
booleanfalse
onOpenChange
(open: boolean) => void
selectionMode
"single" | "multiple""single"
offset
{ x: number; y: number }
disabled
booleanfalse

Trigger

Wrapper for Input and Button. Carries `role="combobox"` and the open-state ARIA attributes. Acts as the positioning anchor for the popup.

AttributeValues
rolecombobox
aria-haspopuplistbox
aria-expandedtrue | false
aria-controlsID of the Content listbox (when open)
aria-disabledtrue (when disabled)

Input

Filter textbox. Opens the listbox on typing or mouse down and forwards navigation keys to the popup.

PropTypeDefault
placeholder
string
AttributeValues
aria-autocompletelist
aria-activedescendantID of the active option

Button

Optional toggle button. Opens or closes the popup and returns focus to the input when opening.

Content

Popup listbox rendered through a portal. Owns active-item tracking, visible-option filtering, and keyboard navigation.

PropTypeDefault
fallback
React.ReactNode
asChild
booleanfalse
AttributeValues
rolelistbox
aria-labelledbyID of the associated trigger
aria-multiselectabletrue (in multi-select mode)

Group

Groups related options. Hides itself when none of its child options match the current filter.

AttributeValues
rolegroup
aria-labelledbyID 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.

PropTypeDefault
value*
string
disabled
booleanfalse
AttributeValues
roleoption
aria-selectedtrue | 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

ShortcutAction
Open the popup if closed, or move to the next option.
Open the popup if closed, or move to the previous option.
HomeMove to the first enabled option.
EndMove to the last enabled option.
EnterSelect the active option.
EscClose the popup.
BackspaceIn multi-select mode with an empty input, remove the last selected value.

Accessibility

The Combobox component implements the WAI-ARIA Combobox pattern:

  • Trigger carries role="combobox" with aria-haspopup="listbox" and aria-expanded.
  • Input exposes aria-autocomplete="list" and tracks the active option via aria-activedescendant.
  • Content renders as role="listbox" with aria-multiselectable in multi-select mode.
  • Each Option exposes role="option" with aria-selected reflecting 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.

Previous
Checkbox