Combobox
A field you type into to narrow a list and pick one of its items (or several), never free text.
ui.combobox
components/ui/combobox.tsxUse case
Use it to pick a record from a list too long to scroll: the client on a new invoice, the product on an order line, the employee assigned to a job. Typing narrows the list, the arrows move and Enter picks; the field only ever holds an item from the list. With `multiple` and `ComboboxChips` it holds several (tags on a client).
Use it when
- Picking one record from a long or data-driven list (clients, products)
- Typing part of a name is quicker than scrolling
- The value must be one of the list's items, never free text
- Several values from a long list: `multiple` with `ComboboxChips`
Use something else when
- A short fixed list where no typing is needed (a status, a province): Select
- Free text is allowed and the list only suggests (a city, a street): Autocomplete
- Searching the whole tool to jump to a page or run an action: Command bar
- Filtering the table on the page by text: Search field
Examples
Code
Import
import { Combobox, ComboboxEmpty, ComboboxInput, ComboboxItem, ComboboxList, ComboboxPopup } from "@/components/ui/combobox"Usage
const CLIENTS = [
{ value: "auberge-du-lac-brule", label: "Auberge du Lac Brûlé" },
{ value: "brasserie-la-voute", label: "Brasserie La Voûte" },
{ value: "mairie-de-saint-aurele", label: "Mairie de Saint-Aurèle" },
]
<Combobox items={CLIENTS}>
<ComboboxInput placeholder="Pick a client" aria-label="Client" showClear />
<ComboboxPopup>
<ComboboxEmpty>No client by that name.</ComboboxEmpty>
<ComboboxList>
{(item: (typeof CLIENTS)[number]) => (
<ComboboxItem key={item.value} value={item}>
{item.label}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxPopup>
</Combobox>Rules
- Pass `items` as `{ value, label }` objects: the input shows the label and a form submits the value.
- Always include `ComboboxEmpty` with a sentence saying nothing matched ("No client by that name.").
- Name the input: a `FieldLabel` in a form, or `aria-label`.
- Keep `ComboboxList`: it scrolls inside a `ScrollArea` that fades at its edges, never a bare `overflow-y-auto`.
- The list glides to its new height as you type, its top fixed (useGlide on the popup, built in).