Combobox
Loading example…
Searchable single select (WAI-ARIA combobox with a listbox popup). The input shows the typed
text while editing and the selected label otherwise; focus never leaves the input and the
highlighted option is announced through aria-activedescendant. Works with local options or
with results the caller loads from onSearchChange.
Import
Section titled “Import”import { Combobox } from "@jcsoftdev/ui/forms";Single-component entry points tree-shake to just this component: @jcsoftdev/ui/forms/combobox.
<Combobox aria-label="School" options={schools} placeholder="Search a school"/>| Prop | Type | Default | Description |
|---|---|---|---|
options * |
readonly (ListboxOption | ComboboxGroup)[] |
Options, optionally nested in labelled groups. For async search, pass the current results. | |
value |
string |
Selected option value (controlled). "" means nothing is selected. |
|
defaultValue |
string |
"" |
|
onValueChange |
((value: string, option: ComboboxOption | null) => void) |
||
onSearchChange |
((query: string) => void) |
Called on every keystroke with the text typed, and with "" when the search resets. Debounce in the caller before fetching; the component never delays or cancels requests. |
|
filter |
boolean | ((option: ComboboxOption, query: string) => boolean) |
true |
Local filtering. true (default) matches label, description and keywords ignoring case and accents; false shows options as given (server-side search); a function decides per option. |
maxVisible |
number |
50 |
Most options rendered at once. Default 50. |
loading |
boolean |
false |
Shows the loading status, e.g. while an async search is in flight. |
loadingText |
string |
||
emptyText |
string |
Shown when nothing matches. Defaults to the localized “No results”. | |
clearable |
boolean |
true |
Shows a button that clears the selection. Default true. |
clearLabel |
string |
||
valueLabel |
string |
Label to show for value while it is not (yet) among options, e.g. after an async search moved on. |
|
name |
string |
Submits the value (not the typed text) with a surrounding <form> through a hidden input. |
|
invalid |
boolean |
||
nativeRequired |
boolean |
false |
required always sets aria-required. The native attribute, which blocks form submission with the browser’s own bubble before your validation can render, is added only when this is true. Default false. |
size |
"sm" | "md" |
"md" |
|
container |
HTMLElement | null |
Portal target for the popup. Defaults to document.body; pass an element to keep a scoped data-style. |
|
material |
"solid" | "glass" | "glass-clear" | "liquid" | "liquid-clear" |
Popup surface material; see PopoverContent. |
|
classNames |
Partial<Record<ComboboxPart, string>> |
Per-part classes merged with cn; consumer classes win. className still targets the root and is merged last. |
* marks a required prop.
It also accepts the native props of the element or primitive it renders (for example className, id, aria-* and event handlers).
Storybook stories
Section titled “Storybook stories”- Default
- Keyboard
- Escape Keeps The Selection
- Clearable
- Not Clearable
- Backspace Clears An Emptied Field
- Submits The Value Not The Text
- Inside Field
- Groups And Custom Empty Text
- Async Options
- Spanish
- Controlled
- Required Leaves Validation To The App
- Native Required
Source
Section titled “Source”packages/ui/src/forms/combobox/combobox.tsx