Combobox

Combobox

Markdown

An editable input with a filterable popup for choosing one or more values.

Use Combobox when people need to type to narrow a list or when the popup needs custom rows. Use Select for a fixed list opened by a button, and Command for an application command palette.

Framework search

Installation

$npx shadcn@latest add @patchui/combobox

The copied source is available in the registry JSON. The canonical implementation lives in packages/react/src/components/combobox.tsx.

Usage

<Label htmlFor="framework">Framework</Label>
<Combobox value={query} onValueChange={setQuery}>
  <ComboboxInput id="framework" />
  <ComboboxPopup>
    <ComboboxItem value="react">React</ComboboxItem>
  </ComboboxPopup>
</Combobox>

Combobox does not filter data. Keep the query on the root, filter in your application, and render the matching items.

Composition

Combobox
├── ComboboxInput
└── ComboboxPopup
    ├── ComboboxSection (optional)
    │   ├── ComboboxGroupLabel
    │   └── ComboboxItem
    └── ComboboxDivider (optional)

ComboboxInput and ComboboxPopup are the minimum useful relationship. Only ComboboxItem participates in option selection and keyboard navigation. Section labels, dividers, and arbitrary popup content are optional.

Examples

Custom content and sections

Add explanatory content directly to the popup, then group selectable items with ComboboxSection. Plain content is not part of keyboard navigation.

Grouped results

Multiple selection

Set multiple, then control the selected values separately from the query. An item with onRemove exposes an explicit remove action for selected rows.

Multiple frameworks

API reference

The wrapper accepts the underlying Base UI and native element props. The entries below cover behavior added or coordinated by Patch UI. See the canonical source for exhaustive TypeScript definitions.

PropTypeDefaultDescription
value / onValueChangestring / (value: string) => void-Controlled query shared by the desktop input and responsive mobile input.
open / onOpenChangeboolean / (open: boolean) => void-Controlled popup state.
autoHighlightboolean | "always"falseDetermines whether an option is highlighted automatically on open or input change.
multiplebooleanfalseEnables Base UI multiple-selection behavior.
selectedValues / onSelectedValuesChangereadonly unknown[] / (values: unknown[]) => void-Controlled selection array and its change handler.
ComboboxInput.clearable / onClearboolean / () => voidfalse / -Shows the built-in clear action and lets the application reset related local state.
ComboboxItem.onRemove / removeLabel() => void / string- / "Remove"Adds an explicit, accessibly named remove action for selected rows.

ComboboxInput also supports variant="unstyled" and hideChevron for composed input surfaces. ComboboxPopup exposes separate desktop and mobile class names when its responsive layouts need different sizing. Use ComboboxPrimitive when an advanced requirement needs a Base UI part that the Patch UI wrapper does not expose directly.

Accessibility

  • Keep a visible label associated with the input. A placeholder is not a label.
  • Real focus remains on the input while the active option is announced through the combobox relationship.
  • Arrow keys move through options. Enter selects the active option. Escape closes the popup. Arrow Down opens a closed popup.
  • With the default autoHighlight={false}, opening the popup does not preselect an option. Move to an option before pressing Enter.
  • Only ComboboxItem is selectable. Do not make plain popup content look like an option.
  • Give each onRemove action a specific removeLabel, such as Remove React.

Responsive behavior

On desktop, the popup is anchored to the input and matches its minimum width. Below the md breakpoint it becomes a centered panel with its own focused search input, narrow viewport gutters, and locked body scroll. Query and placeholder state are shared across both inputs. Token-based surfaces, text, boundaries, and focus styles adapt automatically in dark mode.