Combobox

A select you can type into. Reach for it when the list is long enough that scanning it is work.

Basic

const [resort, setResort] = useState<string>();
<Combobox
options={resorts}
value={resort}
onValueChange={setResort}
label="Resort"
placeholder="Choose resort…"
/>

Combobox or Select?

Select is the default. It is one keystroke to open and one to pick, and a short list is faster to scan than to describe. Reach for Combobox when the list is long enough that finding an option is the slow part — resorts, sites, staff, accounts — or when people already know the name they want and typing beats hunting.

Options can carry keywords, matched while searching but never shown. The resorts above are searchable by region and state code, so typing west finds four — including Stone Creek Landing, whose region is midwest — without any of those words appearing in a row.

Matching is plain substring, not fuzzy. cmdk scores subsequences by default, which meant west also matched Birch Hollow by picking w-e-s-t out of “Hollow northeast”. In a picker, predictable beats clever. Results stay in the order you declared them, too — a list that reshuffles while you type is hard to aim at.

Labelling

The trigger is a button, not an input, so a wrapping <label> will not name it — the same trap as Select and DatePicker. Pass label, and keep it identical to whatever text you show beside the control, so a screen reader and a sighted user hear the same name.

<label className="text-sm text-ink-soft">Resort</label>
<Combobox label="Resort" options={resorts} /> {/* same words, on purpose */}

Anatomy

Filtering and keyboard navigation come from cmdk, because Radix has no combobox primitive. Everything visible is Summit's: the popover is the overlay material, options are the same menu rows as Select and DropdownMenu, and the search row is transparent with a hairline under it — a field well inside the popover would be a second material stacked on glass.

The list is capped at max-h-60 and scrolls. The popover matches the trigger width via --radix-popover-trigger-width; pass contentClassName to override.