Skip to content

Combo Boxes

A combobox is a Picker that lets the user type to filter the options. The design system has no dedicated Combobox export; you build the pattern by placing a Command (the searchable list primitive, built on cmdk) inside a Popover. The trigger shows the current selection, the popover holds a CommandInput plus a filtered CommandList. The live demo below shows the Command list on its own, which is the searchable core of the pattern.

Live demo

The interactive story below runs from the deployed Storybook.

Usage

Source: command.tsx, popover.tsx

The Command searchable list on its own:

import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
} from "@beacon/design-system";
<Command className="rounded-lg border shadow-md w-[350px]">
<CommandInput placeholder="Type a command or search..." />
<CommandList>
<CommandEmpty>No results found.</CommandEmpty>
<CommandGroup heading="Suggestions">
<CommandItem>Calendar</CommandItem>
<CommandItem>Search Emoji</CommandItem>
<CommandItem>Calculator</CommandItem>
</CommandGroup>
</CommandList>
</Command>

The combobox composition: Command inside a Popover, with a trigger that reflects the selection.

import {
Button,
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
Popover,
PopoverContent,
PopoverTrigger,
} from "@beacon/design-system";
const [open, setOpen] = React.useState(false);
const [value, setValue] = React.useState("");
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button variant="outline" role="combobox" aria-expanded={open}>
{value || "Select framework..."}
</Button>
</PopoverTrigger>
<PopoverContent className="w-[200px] p-0">
<Command>
<CommandInput placeholder="Search framework..." />
<CommandList>
<CommandEmpty>No framework found.</CommandEmpty>
<CommandGroup>
<CommandItem onSelect={(v) => { setValue(v); setOpen(false); }}>
Next.js
</CommandItem>
<CommandItem onSelect={(v) => { setValue(v); setOpen(false); }}>
Remix
</CommandItem>
</CommandGroup>
</CommandList>
</Command>
</PopoverContent>
</Popover>

Parts

There is no Combobox component; the pattern is assembled from these exports.

PartRole
CommandRoot searchable list. Filters its items as the input changes (cmdk).
CommandInputThe search field at the top (renders a search icon).
CommandListScroll container for the results.
CommandEmptyShown when no item matches the query.
CommandGroupGroups items under an optional heading.
CommandItemA selectable row; use onSelect to capture the choice.
CommandSeparatorDivider between groups.
CommandShortcutRight-aligned hint text (e.g. a keyboard shortcut) inside an item.
CommandDialogVariant that renders the command list inside a centered dialog (command-palette style).
Popover / PopoverTrigger / PopoverContentWrap Command to turn it into a field that opens on click. Use PopoverContent className="w-[...] p-0".

When to use

  • A picker with many options where typing to filter is faster than scrolling.
  • An app-wide command palette (use CommandDialog).
  • Autocomplete fields where the user selects from a known set.

Do not reach for this pattern when the list is short and fixed; a plain Picker is simpler and needs no filtering. For free-text entry that is not constrained to a list, use a text Input instead.