Combobox
Filterable select — cmdk list inside a Popover, with Select's visual footprint.
Combobox is the searchable alternative to Select: an input that filters
the option list client-side as you type. It wraps cmdk inside srui's
Popover, and its trigger matches Select's height and surface treatment.
Installation
import { Combobox } from "@iammikz/srui";
Usage
Single selection (controlled)
const options = [
{ value: "react", label: "React" },
{ value: "vue", label: "Vue" },
{ value: "svelte", label: "Svelte" },
{ value: "solid", label: "Solid" },
];
const [value, setValue] = useState("");
<Combobox
options={options}
value={value}
onChange={setValue}
placeholder="Framework…"
emptyText="No framework matches."
/>
Multiple selection
Items toggle with checks and the popover stays open until you click away.
Pass values (controlled) or defaultValues — either implies multi mode —
or set multiple explicitly.
Selected: react, svelte
const [values, setValues] = useState(["react"]);
<Combobox
options={options}
multiple
values={values}
onValuesChange={setValues}
placeholder="Frameworks…"
/>
Uncontrolled
Skip value/values and the combobox owns its state — defaultValue (or
defaultValues) seeds it:
<Combobox options={options} defaultValue="vue" placeholder="Framework…" />
Invalid
<Combobox options={options} invalid placeholder="Pick one…" />
Props
| Prop | Type | Default | Description |
|---|---|---|---|
options | { value: string; label: string }[] | — | The option list |
value | string | — | Selected value (controlled, single mode) |
values | string[] | — | Selected values (controlled, multi mode) — implies multiple |
defaultValue / defaultValues | string / string[] | — | Initial selection without controlling; defaultValues implies multiple |
multiple | boolean | false | Multi-select mode: check-toggles, popover stays open |
onChange | (value: string) => void | — | Single mode: fires with the picked value (empty string deselects) |
onValuesChange | (values: string[]) => void | — | Multi mode: fires with the full selection after every toggle |
placeholder | string | "Select…" | Trigger + filter input placeholder |
emptyText | string | "No results found." | Empty-state text; English default, override for i18n |
invalid | boolean | false | Destructive trigger border + aria-invalid |
disabled | boolean | false | Disables the trigger |
Examples
Disabled
Accessibility
The filter input is a real textbox with aria-expanded on the trigger;
cmdk drives arrow-key movement, Enter to commit, and Escape to close, and
announces the highlighted option. The empty state is text content, so it's
read naturally when filtering empties the list.