Combobox
Searchable text input with a dropdown of filterable options; use for long lists where a plain select is awkward
A combobox built on Ark UI Combobox. The default <Combobox /> wires filtering, collection, and list UI for you. For full control over markup or data flow, use the compound parts (ComboboxRoot, ComboboxInput, etc.).
import { Combobox } from "@/components/ui/combobox";
export default function Example() {
return (
<Combobox
label="Framework"
placeholder="Search framework..."
items={[
{ label: "React", value: "react" },
{ label: "Vue", value: "vue" },
{ label: "Svelte", value: "svelte" },
]}
/>
);
}
Installation
liminal add combobox
Usage
Pass items as an array of { label, value, disabled? }. The input filters options with case-insensitive matching. Use emptyText when no item matches the query.
import { Combobox } from "@/components/ui/combobox";
export default function Example() {
return (
<Combobox
label="Framework"
placeholder="Search framework..."
emptyText="No matches."
items={[
{ label: "React", value: "react" },
{ label: "Vue", value: "vue", disabled: true },
{ label: "Svelte", value: "svelte" },
]}
/>
);
}
Examples
Compound API
Use ComboboxRoot with useListCollection and useFilter from Ark UI to mirror the convenience behavior, or customize collection and item rendering. Export also includes ComboboxLabel, ComboboxControl, ComboboxInput, ComboboxTrigger, ComboboxContent, ComboboxItem, and ComboboxEmpty.
import { useListCollection } from "@ark-ui/react/combobox";
import { useFilter } from "@ark-ui/react/locale";
import {
ComboboxRoot,
ComboboxLabel,
ComboboxControl,
ComboboxInput,
ComboboxTrigger,
ComboboxContent,
ComboboxItem,
ComboboxEmpty,
} from "@/components/ui/combobox";
type Item = { label: string; value: string };
const items: Item[] = [
{ label: "React", value: "react" },
{ label: "Vue", value: "vue" },
];
export default function Example() {
const { contains } = useFilter({ sensitivity: "base" });
const { collection, filter } = useListCollection({
initialItems: items,
itemToString: (item) => item.label,
itemToValue: (item) => item.value,
filter: contains,
});
return (
<ComboboxRoot
collection={collection}
onInputValueChange={(d) => filter(d.inputValue)}
>
<ComboboxLabel>Framework</ComboboxLabel>
<ComboboxControl>
<ComboboxInput placeholder="Search..." />
<ComboboxTrigger aria-label="Toggle combobox" />
</ComboboxControl>
<ComboboxContent>
<ComboboxEmpty>No results found.</ComboboxEmpty>
{collection.items.map((item) => (
<ComboboxItem key={item.value} item={item}>
{item.label}
</ComboboxItem>
))}
</ComboboxContent>
</ComboboxRoot>
);
}
For most cases, the convenience <Combobox items={...} /> is enough.
API
Props listed below are specific to the convenience component. The root also accepts Ark Combobox.Root props (for example value, onValueChange, selectionBehavior). See the Ark Combobox docs for the full API.
| Prop | Type | Default | Description |
|---|---|---|---|
| items | { label: string; value: string; disabled?: boolean }[] | - | Options shown in the list (convenience API). |
| label | string | - | Optional field label above the control. |
| placeholder | string | "Search..." | Placeholder for the input. |
| emptyText | string | "No results found." | Message when the filtered list is empty. |