Combobox
A text field that suggests and completes — one value or several as chips, from a static list or a server, with values created from what was typed.
Web only — React, from @krizaka/ui/combobox. Beta: its API may still change in a minor version.
When to use
- To choose among many values the person knows by name: a creator, a country, a model, a playlist.
- With
onSearchwhen the values live on a server (debounced, the previous request aborted). - With
multiplefor several values (collaborators, categories), andcreatablewhen a new one can be added.
When not to use
- For fewer than about seven options known in advance: radios or a select.Use instead: Radio group
- For free words without a closed list (tags, keywords): a tag input.Use instead: Tag input
- To run a search and show results: a search field.Use instead: Search field
Installation
Install
npm install @krizaka/ui @krizaka/tailwind @krizaka/tokens tailwindcssStyles
@import "tailwindcss";
@import "@krizaka/tailwind";
@import "@krizaka/ui/tailwind.css";Import
import { Combobox } from "@krizaka/ui/combobox";Examples
From a server
onSearch: creators fetched as you type, debounced, the stale request aborted.
Several values
Collaborators as chips; Backspace removes the last one, at most three.
Up to three collaborators share the revenue of this video.
Create a value
Pick a playlist or create one from what was typed.
With an error
A required choice left empty: the error is read with the field.
Choose your country to receive payouts.
Props
A text field that suggests, filters and completes: one value or several (chips), static or fetched, creatable.
| Prop | Type | Default | Description |
|---|---|---|---|
labelrequired | string | — | The visible label of the field, passed translated (also its accessible name). |
className | string | — | Classes merged on the root. |
creatable | boolean | — | Offers to create the query as a new value when no option has that exact label. |
debounce | number | — | The wait, in ms, between the last key and onSearch. Default 250. |
defaultValue | ComboboxOption | readonly ComboboxOption[] | null | — | The chosen option at first, uncontrolled. The chosen options at first, uncontrolled. |
disabled | boolean | — | Not available. |
error | string | — | An error under the field: marks it invalid and is read with it. |
filter | ((option: ComboboxOption, query: string) => boolean) | — | Whether an option matches a query. Default: its label contains the query, ignoring case and accents. |
hideLabel | boolean | — | Hides the label visually, keeping it as the accessible name (a search bar with its own context). |
hint | string | — | A help text under the field. |
id | string | — | The id of the text input (default: generated). |
labels | Partial<ComboboxLabels> | — | The words, passed translated; English by default. |
maxSelected | number | — | Most options that can be chosen (several values only). Most options that can be chosen; the list stops offering more past it. |
multiple | boolean | — | One value (default) or several. Several values, shown as chips. |
name | string | — | The name of a hidden input holding the value(s), for a plain <form> post. |
onCreate | ((query: string) => ComboboxOption) | — | Turns a query into the created option (an id from the server…). Default { value: query, label: query }. |
onSearch | ((query: string, signal: AbortSignal) => Promise<readonly ComboboxOption[]>) | — | Fetches the options for a query (debounced by debounce); the signal aborts when a newer query starts. |
onValueChange | ((value: ComboboxOption | null) => void) | ((value: ComboboxOption[]) => void) | — | Called with the chosen option, or null when it is cleared.
Called with every chosen option. |
options | readonly ComboboxOption[] | — | The options, filtered as the person types (by filter). |
placeholder | string | — | The input's placeholder, passed translated. |
separators | readonly string[] | — | Keys that create the query at once, as Enter does ([","] for tags); a paste is split on them too. |
value | ComboboxOption | readonly ComboboxOption[] | null | — | The chosen option (controlled), null for none.
The chosen options (controlled). |
Accessibility
- The ARIA 1.2 combobox pattern: the focus stays in the input,
aria-activedescendantpoints at the active option of thelistbox. - The number of results is announced in a polite live region (
labels.results). - Chosen options carry
aria-selected; each chip's remove button is named (“Remove Eric”). - The label is a real
<label>;hintanderrorare wired witharia-describedby,errorsetsaria-invalid.
Keyboard
| Keys | Action |
|---|---|
| Arrow Down / Arrow Up | Open the list and move the active option. |
| Home / End | First or last option, when the list is open. |
| Enter | Choose the active option (or create the typed value). |
| Esc | Close the list; for one value, restore its label. |
| Backspace | In an empty input, remove the last chip. |
Best practices
- Write
labelas the question (“Collaborators”), theplaceholderas an example (“Type a name”). - Return at most 20 options from
onSearch; put the best match first. - Give options a
descriptionwhen names collide (two creators named Eric: their handles). - Set
maxSelectedwhen the product has a limit, and say it inhint.
Related components
Generated from the code of @krizaka/ui 2.4.0: its meta.ts, its examples and its types.Edit this documentation on GitHub