Summit
ComponentsSelection

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

ElementUsage
InputRequired
TriggerShown by default
Input groupRequired
Clear buttonWhen 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

ElementUsage
ItemRequired
CheckSelected item only
PopupRequired

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

ElementUsage
ChipOne for each value
InputRequired
Remove buttonShown by default
Chips fieldRequired

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

StringRuleExampleCounterexample
PlaceholderSay what to choose“Choose a client”“Search…”
Empty messageName 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

KeyResult
TabMoves focus to the input, then to the trigger. If the list is open, closes it and restores the selected label.
A characterOpens the list and filters it
ArrowDown, ArrowUpOpens 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.
EnterSelects the highlighted option. On the trigger, opens the list.
EscapeCloses the list. If the list is closed, clears the value, including all chips.
ArrowLeft at the start of a chips inputMoves focus to the last chip. ArrowLeft and ArrowRight then move between the chips and back to the input.
Backspace in an empty chips inputRemoves the last chip
Backspace or Delete on a chipRemoves that chip

Requirements

The input of a Combobox needs a name so that screen readers can announce it, as WCAG 2.2 SC 4.1.2 Name, Role, Value requires. To provide one, place it in a Field with a 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/combobox

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

Several Values
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.

With a Clear Button
<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

PropTypeDefaultDescription
showTriggerbooleantrueShows the trigger
showClearbooleanfalseReplaces the trigger with a clear button while a value is set
disabledbooleanfalseDisables the input and the trigger
classNamestringNoneClasses for the Input Group

ComboboxContent

PropTypeDefaultDescription
side'top' | 'bottom' | 'left' | 'right' | 'inline-start' | 'inline-end''bottom'The side of the field the list opens on
sideOffsetnumber | OffsetFunction6The gap between the field and the list, in pixels
align'start' | 'center' | 'end''start'The edge of the field the list is aligned with
alignOffsetnumber | OffsetFunction0A shift along that edge, in pixels
anchorAn element or a refThe inputThe element the list is positioned against

ComboboxChip

PropTypeDefaultDescription
showRemovebooleantrueShows the remove button

On this page