Combobox
An input that filters a list of options as you type.
One combobox, two shapes. The default (showTrigger is true) is the Select-shaped one: a
chevron you click to open the whole list, which then narrows as you type. Pass
showTrigger={false} and you have the Autocomplete shape: no button, opens on
type. Same machine, same props, one page — which is why there is no separate Autocomplete
component to choose between. Everything here applies to both.
Usage
import {
Combobox,
ComboboxContent,
ComboboxEmpty,
ComboboxInput,
ComboboxItem,
useFilter,
useListCollection,
} from "@kanzo-tech/ui";<Combobox
collection={collection}
onInputValueChange={(details) => filter(details.inputValue)}
>
<ComboboxInput placeholder="Find a member…" />
<ComboboxContent>{/* items */}</ComboboxContent>
</Combobox>Filtering is yours to own — the machine never mutates the collection. useListCollection
holds the items and gives you a filter(inputValue), and useFilter supplies a locale-aware
contains so accents and case do not block a match.
Anatomy
Two more ship and neither is in the tree. ComboboxPositioner is the floating box ComboboxContent
places itself in, for a listing you position yourself. ComboboxContext is the render prop — it
takes a function rather than elements and renders nothing of its own, which is how a caller reads
the input value or the highlighted item without a hook.
Combobox
├── ComboboxInput (wraps ComboboxControl + InputGroup)
│ ├── ComboboxTrigger
│ └── ComboboxClear
└── ComboboxContent
├── ComboboxEmpty
├── ComboboxList
└── ComboboxGroup
├── ComboboxGroupLabel
└── ComboboxItemWith field
Only members who are ready today.
Groups
Autocomplete
Drop the trigger and the control stops advertising a list: it is an input that opens once the user types. That is the whole difference between what other libraries ship as a "Select" and as an "Autocomplete", so it is one prop here rather than a second component.
Use it when the field reads as a search box and the list would be too long to be worth presenting up front. Keep the trigger when the user cannot be expected to know what is in the list.
Custom values
By default the machine owns the value, so it reverts the input on blur if what you typed
matches nothing — the list is a closed set. allowCustomValue turns that off and lets the typed
text stand.
The selection is still only ever an item from the collection. A custom value reaches you through
onInputValueChange, and it is yours to keep: push it into the collection, submit it as free
text, or validate and reject it.
Clearable
The clear button only appears once there is something to clear, and it replaces the open trigger rather than crowding beside it.
Disabled
Multiple selection
Yes — one prop, and no need to reach for a different component.
Setting multiple also switches Ark's selectionBehavior to clear, so the input empties
after each pick and the list is immediately ready for the next one. Picking five things does not
mean clearing your query five times.
The chips showing what is selected are the caller's. The component owns the value; how you
display it is a presentation decision, and a row of badges is only one answer — a summary line
or a removable-token input are others. If the values do not exist beforehand at all, you want
TagsInput instead.
Keyboard
| Key | Does |
|---|---|
| ↓ / ↑ | Opens the list and highlights the first / last option; once open, moves the highlight, wrapping at the ends. |
| Alt+↓ / Alt+↑ | Opens the list with nothing highlighted / closes it. |
| Home / End | Highlights the first / last option while the list is open, and moves the caret while it is closed. |
| Enter | Selects the highlighted option and closes the list; under multiple it keeps the list open and empties the input. |
| Esc | Closes the list, then on a second press reverts the typed text to the selected value unless allowCustomValue. |
Holding Ctrl or Shift hands the key back to the text field, so Shift+Home selects the query rather than jumping to the first option.
API Reference
comboboxItemVariants is exported for a row you assemble yourself: the highlighted, selected and disabled states are the ones a hand-written option always forgets.
Combobox
| Prop | Type | Default |
|---|---|---|
collection | ListCollection | — |
multiple | boolean | false |
allowCustomValue | boolean | false |
openOnClick | boolean | true |
lazyMount | boolean | true |
unmountOnExit | boolean | true |
Everything else passes through to Combobox.Root — value / defaultValue (always a
string[]), onValueChange, inputValue, onInputValueChange, name, form, disabled,
invalid, readOnly, positioning.
ComboboxInput
| Prop | Type | Default |
|---|---|---|
size | "sm" | "md" | "lg" | "md" |
showTrigger | boolean | true |
showClear | boolean | false |
Renders ComboboxControl and an InputGroup around Combobox.Input. Use
ComboboxFieldInput instead when you need the bare input inside your own control.
ComboboxItem
| Prop | Type | Default |
|---|---|---|
showIndicator | boolean | true |
ComboboxGroup
| Prop | Type | Default |
|---|---|---|
heading | string | React.ReactNode | — |
ComboboxFieldInput is the bare Combobox.Input with no control or trigger around it, for when
you assemble the control yourself.