Combobox
A searchable select built from Popover + Command. Single or multiple selection, flat or grouped options, a per-option avatar / icon / trailing badges, and an optional 'Add new' action. Reach for it instead of Select when the list is long or needs type-ahead.
Anatomy
- 1Trigger
A Select-style button (h-9, border-input, no shadow). Shows the selected label (+ optional avatar) or the muted placeholder, with a CaretUpDown on the right.
- 2Search input
CommandInput at the top of the popover. Filters the list as you type (cmdk).
- 3List + empty
CommandList of CommandItems; CommandEmpty shows the empty text when nothing matches.
- 4Selected check
A bold primary Check on the right of the active option.
- 5Group-label trigger (optional)
Pass groupLabel for a taller (h-12) trigger with a small label above the value and a CaretDown.
States
Placeholder shown, list closed. Open with click, Enter, or the arrow keys.
<Combobox
options={countries}
placeholder="Select a country"
/>The chosen label (and its avatar) show in the trigger; reopening marks it with a check.
<Combobox
options={providers} // each option carries an avatar
defaultValue="adyen"
/>A taller trigger that keeps a persistent field label (e.g. Country) above the value.
<Combobox
options={countries}
groupLabel="Country"
placeholder="Select a country"
/>Set multiple. Selected options show as removable chips with a Delete all shortcut and a +N overflow; list items get a checkbox.
<Combobox
multiple
options={methods}
defaultValue={["card", "pix"]}
placeholder="Select methods"
/>Pass grouped options for headings, plus onAddNew for a pinned 'Add new' action at the bottom.
<Combobox
options={grouped} // [{ heading, options }]
onAddNew={() => openCreate()}
placeholder="Select a method"
/>Import
Copy this import line at the top of the file where you compose this atom.
import { Combobox } from "@/components/ui/combobox";Props
Everything else from the underlying HTML or Radix primitive is forwarded via ...props.
| Prop | Type | Default | Description |
|---|---|---|---|
| options | ComboboxOption[] | ComboboxGroup[] | — | { value, label, avatar?, icon?, badges?, disabled? }, or [{ heading, options }] for grouped lists. |
| multiple | boolean | false | Multiselect mode: removable chips in the trigger + checkbox list items. Value becomes string[]. |
| value / defaultValue | string | string[] | — | Controlled or uncontrolled selected value (string, or string[] when multiple). |
| onValueChange | (value: string | string[]) => void | — | Fires on select. In single mode, re-selecting clears; in multiple mode, toggles. |
| placeholder | string | 'Select option' | Trigger text when nothing is selected. |
| searchPlaceholder | string | 'Search…' | Placeholder inside the search input. |
| emptyText | string | 'No results found.' | Shown when the search matches nothing. |
| groupLabel | string | — | Single only: taller (h-12) two-line trigger with a persistent label above the value. |
| maxChips | number | 3 | Multiple only: chips shown in the trigger before the rest collapse into +N. |
| onAddNew / addNewLabel | () => void / string | — | Pins an 'Add new' action (PlusCircle item) at the bottom of the list. |
| disabled | boolean | false | Dims the trigger and blocks opening. |
| className | string | — | Classes on the trigger (set the width here). |
| contentClassName | string | — | Classes on the popover content (width defaults to the trigger width). |
| id | string | — | Associates the trigger with an external Label via htmlFor. |
When to use
- A single choice from a long list (countries, currencies, providers).
- Any select that benefits from type-ahead search.
- A picker where options read better with an avatar or logo.
When not to use
- A short, fixed list (≤ ~8 options) — use Select.
- Multiple selections — use a Checkbox list or a multi-select.
- A free-text field — use Input.
Usage
- Keep option labels short so the trigger doesn't truncate.
- Show a check on the selected option so the current value is obvious.
- Write a helpful empty state ('No results found.').
- Don't use it for booleans — that's a Switch or Checkbox.
- Don't hide the search when the list is long — that's the whole point.
- Don't put a drop shadow on the trigger — Yuno's no-shadow-on-inputs rule.
Related
Cross-links to atoms and patterns you may reach for next.