Skip to content
GetUrUI

Combobox

New
.md

Type-to-filter combobox: matched text lights up in volt, a create row offers what you typed, async results load behind a spinner, and an empty state wobbles in when nothing matches.

comboboxautocompletesearchselectformasync

Installation

$npx shadcn@latest add @geturui/combobox
Download source (.zip)

Also installs: Field, Spinner

Usage

usage.tsx
1import * as React from "react";
2import { Combobox, type ComboboxOption } from "@/components/ui/combobox";
3
4export function LabelPicker() {
5  const [labels, setLabels] = React.useState<ComboboxOption[]>([
6    { value: "bug", label: "Bug", dot: "danger" },
7    { value: "design", label: "Design", dot: "info" },
8  ]);
9  const [value, setValue] = React.useState<string | null>(null);
10  return (
11    <Combobox
12      label="Label"
13      options={labels}
14      value={value}
15      onValueChange={setValue}
16      onCreate={(text) => {
17        setLabels((l) => [...l, { value: text, label: text }]);
18        setValue(text);
19      }}
20    />
21  );
22}

Props

PropTypeDefaultDescription
options*ComboboxEntry[]—{ value, label, description?, icon?, avatar?: boolean | string, dot?: "success" | "warning" | "danger" | "info" | "neutral", meta?, shortcut?, disabled?, keywords? }, a group { heading, options } or { separator: true }
value / defaultValue / onValueChangestring | null—Selected value, controlled or uncontrolled.
inputValue / defaultInputValuestring—Text in the input, controlled or uncontrolled.
onInputChange(text) => void—Every keystroke. Fetch here and pass the results back as options.
filterfalse | (option, query) => boolean—Custom match test, or false when options arrive already filtered.
loadingbooleanfalseSpinner in the well, plus a loading row while there are no results.
onCreate(text) => void—Adds a Create “text” row when nothing matches exactly.
createLabel(text) => string—Wording for the create row.
emptyText / emptyDescriptionReactNode—Empty state title and hint.
size"sm" | "md" | "lg""md"Well height 32 / 40 / 48, matching Button. Rows, icons and the list height scale with it.
label / hint / errorReactNode—Field chrome. Any error marks the control invalid and swaps the hint for the message.
requiredbooleanfalseVolt asterisk on the label and aria-required on the control.
disabledbooleanfalseDims the well and blocks interaction.
namestring—Form field name; values post through hidden inputs.
placeholderstring"Search"Input placeholder.
iconLeadingComponentType<{ className }>SearchWell icon, replaced by the selected option's media.
openOnFocusbooleanfalseOpen the list as soon as the input is focused.

Accessibility

  • APG combobox with list autocomplete: focus stays in the input and aria-activedescendant tracks the highlighted option.
  • Down/Up open and move, Enter picks, Escape closes and a second Escape clears the text.
  • Leaving the field restores the selected label, or clears the value when the text was emptied.
  • Loading and empty states are announced through role=status; the clear and toggle buttons have labels and stay out of the tab order.

Related