Combobox
A Combobox allows users to filter a list of options by typing and to choose one or several of them.
When to Use
- to choose from a list long enough to search, such as the client of an invoice
- to choose several options from one list, like the clients on a report
When Not to Use
- for a short list that needs no typing (use a Select)
- for free text, as a Combobox only accepts a value from its list (use an Input)
- to search for an action and run it (use Command)
See Select for a comparison of the Select, the Native Select, and the Combobox.
Anatomy
A Combobox is a field and the list that it opens. If multiple is set, the field shows a chip for each value.
Field
| Element | Usage |
|---|---|
| Input | Required |
| Trigger | Shown by default |
| Input group | Required |
| Clear button | When showClear is set and there is a value |
ComboboxInput renders an Input Group that contains the input, the trigger, and the clear button. Its className is applied to the group.
List
| Element | Usage |
|---|---|
| Item | Required |
| Check | Selected item only |
| Popup | Required |
ComboboxContent renders the portal and the popup, and ComboboxItem adds the check. ComboboxEmpty is shown in place of the list when no option matches. To divide a list, use ComboboxGroup, ComboboxLabel, and ComboboxSeparator as you would use their counterparts in a Select.
Chips
| Element | Usage |
|---|---|
| Chip | One for each value |
| Input | Required |
| Remove button | Shown by default |
| Chips field | Required |
If multiple is set, use ComboboxChips in place of ComboboxInput. ComboboxValue provides the selected values, and you render a ComboboxChip for each one.
States
To disable a Combobox, set disabled on ComboboxInput. To mark a Combobox as invalid, set invalid on its Field, or set aria-invalid on ComboboxInput or ComboboxChipsInput, not on Combobox.
Behavior
A Combobox isn’t modal: the page stays interactive while the list is open.
Position and Size
By default, the list opens below the field and is as wide as the field. It has a maximum height of 252px and scrolls when its options are taller.
Clear Button
If showClear is set on ComboboxInput, a clear button replaces the trigger while a value is set. The clear button isn’t in the tab order, so Tab skips it. Keyboard users can clear the value by pressing Escape when the list is closed.
Content
| String | Rule | Example | Counterexample |
|---|---|---|---|
| Placeholder | Say what to choose | “Choose a client” | “Search…” |
| Empty message | Name what was not found | “No clients found.” | “No results.” |
The names of the trigger, the clear button, and a chip’s remove button are set in labels.combobox: “Open popup”, “Clear”, and “Remove” by default. To translate them, use the Summit Provider.
Accessibility
Base UI’s Combobox sets the roles and keeps focus in the input. aria-activedescendant on the input points to the highlighted option.
Keyboard
| Key | Result |
|---|---|
Tab | Moves focus to the input, then to the trigger. If the list is open, closes it and restores the selected label. |
| A character | Opens the list and filters it |
ArrowDown, ArrowUp | Opens the list. If the list is open, moves the highlight to the next or the previous option. From the last option, the highlight returns to the input, then to the first option. |
Enter | Selects the highlighted option. On the trigger, opens the list. |
Escape | Closes the list. If the list is closed, clears the value, including all chips. |
ArrowLeft at the start of a chips input | Moves focus to the last chip. ArrowLeft and ArrowRight then move between the chips and back to the input. |
Backspace in an empty chips input | Removes the last chip |
Backspace or Delete on a chip | Removes that chip |
Requirements
FieldLabel, connect a Label to the id of ComboboxInput or ComboboxChipsInput with htmlFor, or set aria-label on ComboboxInput or ComboboxChipsInput.Installation
npx shadcn@latest add @summit/comboboxThe CLI also adds @summit/button, @summit/input-group, and @summit/summit-provider.
Usage
You provide the options. To have them filtered as users type, pass them to items on Combobox, and pass ComboboxList a function that renders one option. Base UI filters items and calls the function for each match. If you write the options as children of ComboboxList, they aren’t filtered.
If an option has the shape { label, value }, its label is shown in the input.
import {
Combobox,
ComboboxContent,
ComboboxEmpty,
ComboboxInput,
ComboboxItem,
ComboboxList,
} from '@/components/ui/combobox';
const clients = [
{ label: 'Atelier Brume', value: 'brume' },
{ label: 'Fable Bakery', value: 'bakery' },
];
<Combobox items={clients}>
<ComboboxInput aria-label="Client" placeholder="Choose a client" className="w-64" />
<ComboboxContent>
<ComboboxEmpty>No clients found.</ComboboxEmpty>
<ComboboxList>
{(client: (typeof clients)[number]) => (
<ComboboxItem key={client.value} value={client}>
{client.label}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>;Several Values
To allow several values, set multiple on Combobox. To open the list below the whole field, pass the ref that useComboboxAnchor returns to ComboboxChips and to anchor on ComboboxContent.
import {
Combobox,
ComboboxChip,
ComboboxChips,
ComboboxChipsInput,
ComboboxContent,
ComboboxValue,
useComboboxAnchor,
} from '@/components/ui/combobox';
const anchor = useComboboxAnchor();
<Combobox items={clients} multiple>
<ComboboxChips ref={anchor} className="w-80">
<ComboboxValue>
{(selected: typeof clients) =>
selected.map((client) => <ComboboxChip key={client.value}>{client.label}</ComboboxChip>)
}
</ComboboxValue>
<ComboboxChipsInput aria-label="Clients" placeholder="Add a client" />
</ComboboxChips>
<ComboboxContent anchor={anchor} />
</Combobox>;With a Clear Button
To show a clear button while a value is set, set showClear on ComboboxInput.
<ComboboxInput aria-label="Client" placeholder="Choose a client" showClear />API Reference
The parts accept the props of their matching parts in Base UI’s Combobox, where ComboboxContent is Combobox.Popup and ComboboxLabel is Combobox.GroupLabel. See the Base UI Combobox documentation for items, value, onValueChange, multiple, autoHighlight, and filter.
ComboboxInput
| Prop | Type | Default | Description |
|---|---|---|---|
showTrigger | boolean | true | Shows the trigger |
showClear | boolean | false | Replaces the trigger with a clear button while a value is set |
disabled | boolean | false | Disables the input and the trigger |
className | string | None | Classes for the Input Group |
ComboboxContent
| Prop | Type | Default | Description |
|---|---|---|---|
side | 'top' | 'bottom' | 'left' | 'right' | 'inline-start' | 'inline-end' | 'bottom' | The side of the field the list opens on |
sideOffset | number | OffsetFunction | 6 | The gap between the field and the list, in pixels |
align | 'start' | 'center' | 'end' | 'start' | The edge of the field the list is aligned with |
alignOffset | number | OffsetFunction | 0 | A shift along that edge, in pixels |
anchor | An element or a ref | The input | The element the list is positioned against |
ComboboxChip
| Prop | Type | Default | Description |
|---|---|---|---|
showRemove | boolean | true | Shows the remove button |