Forms

Combobox

A text input that filters a list as you type. Single choice with ComboboxInput, several with chips.

packages/design-system/components/ui/combobox.tsx

Examples

Single, type to filter
Multiple, as chips

Anatomy

  1. 01Input group with chevron (or chips row)
  2. 02Popup, dark and blurred
  3. 03Empty state
  4. 04List of items with a check

Usage

import {
  Combobox, ComboboxContent, ComboboxEmpty, ComboboxInput, ComboboxItem, ComboboxList,
} from "@repo/design-system/components/ui/combobox";

<Combobox items={services}>
  <ComboboxInput placeholder="Choose a service" />
  <ComboboxContent>
    <ComboboxEmpty>No service found.</ComboboxEmpty>
    <ComboboxList>
      {(item: string) => (
        <ComboboxItem key={item} value={item}>{item}</ComboboxItem>
      )}
    </ComboboxList>
  </ComboboxContent>
</Combobox>

Props

PropTypeDefaultDescription
items*T[]noneOn the root. ComboboxList's render function is called once per filtered item.
multiplebooleanfalseHold an array of values. Pair it with ComboboxChips.
value / onValueChangeT | T[]noneControlled value, on the root.
itemToStringLabel(item: T) => stringnoneHow an item reads in the input and is matched when filtering.
ComboboxInput showTriggerbooleantrueThe chevron button that opens the list.
ComboboxInput showClearbooleanfalseA clear button, which replaces the chevron once there is a value.
ComboboxContent anchorRefObjectnoneAnchor the popup to the chips row. Get the ref from useComboboxAnchor().
side"top" | "bottom" | "left" | "right" | "inline-start" | "inline-end"noneWhich side of the trigger the popup opens on.
align"start" | "center" | "end""start"How the popup lines up with the trigger along that side.
sideOffsetnumber6The gap between trigger and popup, in pixels.

Guidance

Do

  • Use it when the list is long enough that people will search it.

Don't

  • Use it for fewer than six options. A select or radios are quicker.