Combobox
Pick from a list by typing, wrapping the Base UI Combobox. The input filters as you type, the chevron browses the whole list, and the selection is a real value like any form control. For a short fixed list, the Select stays simpler.
Playground
Every control maps to a prop. Try typing a few letters, then clearing; the Code tab always shows the markup for exactly what you've configured.
Variants
Two inputs and a button: bordered is the default, borderless trades the border for a muted fill, and ComboboxTrigger reads like a Select and moves the typing into the popup.
States
Open, highlighted, and selected are live; try the examples. A selection swaps the chevron for a clear button, disabled dims the whole group, invalid turns the border to the danger color, and focus rings the group on every focus, not just keyboard.
Recipes
The parts compose into the usual bigger patterns without extra props; each recipe below is a complete, paste-ready arrangement.
Multiple select. multiple turns the value into an array, and ComboboxChips shows it as removable chips with the input riding inline after them.
Input inside popup. For a select-like control, swap the input for a ComboboxTrigger and put the search field inside the popup with searchInput on the content.
Grouped. Pass groups as the root's items and render each group's own items through ComboboxCollection; filtering reaches into every group.
Creatable. Manage the items yourself and append a create row when the query matches nothing; selecting it adds the value and keeps it chosen.
Async search
Fetch on onInputValueChange, hand the results to items, and keep a status line up while the request runs; with multiple, picked people stay as chips while new searches stream fresh results into the list. Both demos fake the network with a delay.
Styling states
Items carry data-highlighted and data-selected, the chevron carries data-popup-open, and the popup has the usual data-starting-style/data-ending-style transitions:
.ub-combobox-item[data-highlighted] {
background: var(--ub-accent);
color: var(--ub-accent-contrast);
}Props
Everything Base UI's Combobox parts accept passes through (multiple, itemToStringLabel for object items, onInputValueChange, ...). The essentials:
| Prop | Type | Default | Description |
|---|---|---|---|
ComboboxRoot.items | Value[] | – | The full list; typing filters it and powers the empty state. |
ComboboxRoot.value | Value | Value[] | – | Controlled selection (also defaultValue, onValueChange); multiple makes it an array. |
ComboboxRoot.size | "default" | "compact" | "default" | Sizes the input and the list together: 36px tall with 16px text by default, 28px with 14px text compact. |
ComboboxInput.variant | "default" | "borderless" | "default" | Bordered, or a muted fill with no border. |
ComboboxInput.clearable | boolean | true | While something is selected, the clear button takes the chevron's place. |
ComboboxInput.invalid | boolean | false | Danger border and ring, plus aria-invalid; a surrounding Field sets it automatically. Also on ComboboxTrigger. |
ComboboxContent.empty | ReactNode | – | Shown while the filter matches nothing. |
ComboboxContent.children | (item) => ReactNode | – | Called with each filtered item; render a ComboboxItem. |
ComboboxContent.searchInput | boolean | string | – | Puts the text input inside the popup, for ComboboxTrigger; a string sets its placeholder. |
ComboboxContent.status | ReactNode | – | A politely announced status line above the list, for async searches. |
ComboboxContent.sideOffset | number | 4 | Gap between the input and the popup, in pixels. Also side and align. |
ComboboxTrigger.placeholder | ReactNode | – | Shown while nothing is selected; visual only, so name the trigger with aria-label. |
ComboboxRoot.itemToStringLabel | (item) => string | – | The label to show and filter on when items are objects. |
Agent instructions
Working with a coding agent? Paste this into its context, or point it at llms.txt for the whole library.
ComboboxRoot, ComboboxInput, ComboboxTrigger, ComboboxContent, ComboboxItem, ComboboxGroup, ComboboxGroupLabel, ComboboxChips, ComboboxChip, ComboboxValue, ComboboxCollection, ComboboxStatus, from @usebones/react.
- Structure: ComboboxRoot (pass items; size "default" | "compact") wraps ComboboxInput (placeholder, variant "default" | "borderless", clearable default true, invalid, disabled; chevron built in, swapped for a clear button while something is selected) + ComboboxContent (empty="..." plus function children rendering a ComboboxItem per filtered item).
- value/defaultValue/onValueChange like every control; multiple turns the value into an array. Object items need itemToStringLabel.
- Multiple with chips: ComboboxChips wrapping ComboboxValue's function children (map values to ComboboxChip; put ComboboxInput clearable={false} after them). Chip remove buttons are automatic.
- Select-like: ComboboxTrigger (placeholder is visual only; name it via aria-label or a Field label) with searchInput="..." on ComboboxContent putting the input inside the popup.
- Grouped: items are groups; function children get each group; ComboboxGroup items={group.items} + ComboboxGroupLabel + ComboboxCollection render the rows.
- Async: fetch in onInputValueChange, pass results as items, status="Searching..." on the content while loading (announced politely), empty={null} while loading.
- Creatable: manage items in state, render static children, and append a ComboboxItem whose value is the query when nothing matches.
- Prefer Select for short fixed lists; the combobox earns its input when the list is long enough to search.
- Inside FieldRoot, drop invalid and use FieldLabel and FieldError instead; the Field wires the name and validation.
- Restyle in CSS via .ub-combobox-input-group ([data-variant], [data-size]), .ub-combobox-input ([data-invalid], [data-disabled]), .ub-combobox-chips, .ub-combobox-chip, .ub-combobox-popup, .ub-combobox-item ([data-highlighted], [data-selected]), [data-popup-open] on the chevron. Tokens only.