Combobox
Flexible input for selecting from a list with filtering.
Examples
Basic
Groups
Multi-select with chips
Creatable
Overview
Combobox is a text input paired with a filtered list of options. Use it when the user picks from a known set but the set is too large for a Select or radio group. Built on Base UI Combobox.
import {
Combobox,
ComboboxContent,
ComboboxEmpty,
ComboboxInput,
ComboboxItem,
ComboboxList,
} from "@rogo-technologies/ui/combobox";
<Combobox items={languages} itemToStringLabel={(item) => item.value}>
<ComboboxInput placeholder="Filter..." />
<ComboboxContent>
<ComboboxEmpty>No results.</ComboboxEmpty>
<ComboboxList>
{(item) => (
<ComboboxItem key={item.id} value={item}>
{item.value}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>;Usage
Multi-select with chips
Selected values render as chips inside the input. Type to filter, click an item to add it, click the chip's × to remove. Press Backspace on the empty input to remove the last chip. Useful for sharing flows, tagging, or any input where the user picks several items at once.
import {
Combobox,
ComboboxChips,
ComboboxChip,
ComboboxChipsInput,
ComboboxContent,
ComboboxList,
ComboboxItem,
} from "@rogo-technologies/ui/combobox";
<Combobox multiple items={users} itemToStringLabel={(u) => u.name}>
<ComboboxChips>
{(selected) =>
selected.map((u) => (
<ComboboxChip key={u.id} value={u}>
{u.name}
</ComboboxChip>
))
}
<ComboboxChipsInput placeholder="Add people..." />
</ComboboxChips>
<ComboboxContent>
<ComboboxList>
{(item) => (
<ComboboxItem key={item.id} value={item}>
{item.name}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>;Creatable
Let the user submit a value that isn't in the suggestion list — useful for tags, labels, or any free-form set with hints. Append the typed query to items and render a "Create …" row at the end of the list. With autoHighlight, Enter selects it; clicking works the same. The selection callback receives the new string just like any other item, so there's no separate "create" code path.
const trimmed = query.trim();
const canCreate = trimmed.length > 0 && !suggestions.includes(trimmed) && !tags.includes(trimmed);
<Combobox
multiple
items={canCreate ? [...filtered, trimmed] : filtered}
value={tags}
onValueChange={setTags}
inputValue={query}
onInputValueChange={setQuery}
autoHighlight
>
{/* ...chips input... */}
<ComboboxContent>
<ComboboxList>
{filtered.map((t) => (
<ComboboxItem key={t} value={t}>
{t}
</ComboboxItem>
))}
{canCreate && <ComboboxItem value={trimmed}>Create “{trimmed}”</ComboboxItem>}
</ComboboxList>
</ComboboxContent>
</Combobox>;API
Combobox (Root)
| Prop | Type | Default | Description |
|---|---|---|---|
items | Value[] | — | The full list of selectable items. |
itemToStringLabel | (item: Value) => string | — | Returns the label string used for filtering & display. |
value | Value | Value[] | null | — | Controlled selection. Array when multiple is true. |
defaultValue | Value | Value[] | null | — | Initial selection (uncontrolled). |
onValueChange | (value: Value | Value[]) => void | — | Callback when selection changes. |
multiple | boolean | false | Allow multi-select with chips. |
open | boolean | — | Controlled open state of the popup. |
onOpenChange | (open: boolean) => void | — | Callback when popup open state changes. |
Subcomponents
| Component | Purpose |
|---|---|
ComboboxInput | Single-line text input that opens & filters the list. |
ComboboxChips | Container that renders selected chips alongside input. |
ComboboxChip | One selected value rendered as a removable chip. |
ComboboxChipsInput | Input used inside a ComboboxChips container. Accepts deleteOnBackspace (default true) — when true, pressing Backspace on the empty input removes the last chip. |
ComboboxContent | Floating popup wrapper. |
ComboboxList | List region; render-prop maps over the filtered items. |
ComboboxItem | A single selectable row. |
ComboboxGroup | Group rows under a labeled section. |
ComboboxLabel | Visible label rendered inside a ComboboxGroup. |
ComboboxEmpty | Shown when the filter has no matches. |
ComboboxSeparator | Divider between items. |
ComboboxClear | Button to clear the current selection. |
ComboboxTrigger | Button that opens the popup (alternative to typing). |
ComboboxInputGroup | Wraps input + trigger/clear into one styled row. |
ComboboxValue | Renders the currently selected value (for triggers). |
All subcomponents accept standard HTML attributes for their underlying elements.
Guidelines
Do
- Use Combobox when the user picks from a known set that's too large to scan (more than ~7 items)
- Provide an
itemToStringLabelthat matches what users would type - Show a
ComboboxEmptystate — never leave the popup blank when filtering yields nothing - Use multi-select with chips for tagging, sharing, and similar "pick several" flows
Don't
- Don't use Combobox for free-form text entry — use
Inputinstead - Don't use Combobox for short fixed lists (≤ 5 options) — use
SelectorRadioGroup - Don't render hundreds of items eagerly — virtualize or paginate the source data
- Don't hide the filtered list while the input has focus — users expect to see matches as they type