Home

Combobox

A field you type into to narrow a list and pick one of its items (or several), never free text.

ui.comboboxcomponents/ui/combobox.tsx

Use case

For the AI

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

Type to narrow, arrows to move, enter to pick

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