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

PropTypeDefaultDescription
options{ value: string; label: string }[]—The option list
valuestring—Selected value (controlled, single mode)
valuesstring[]—Selected values (controlled, multi mode) — implies multiple
defaultValue / defaultValuesstring / string[]—Initial selection without controlling; defaultValues implies multiple
multiplebooleanfalseMulti-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
placeholderstring"Select…"Trigger + filter input placeholder
emptyTextstring"No results found."Empty-state text; English default, override for i18n
invalidbooleanfalseDestructive trigger border + aria-invalid
disabledbooleanfalseDisables 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.