Components
Combobox
A searchable select. It pairs a text input with a dropdown list so the reader can filter by typing, which keeps long option sets manageable.
Combobox is a higher-order component, composed from the Command and Popover primitives. The Popover positions the list; Command supplies the search input, filtering, and keyboard navigation.
Preview
Rendered with live Folio tokens. Open it and type to filter, no dark: classes.
Variants
<Combobox options={regions} />// Combobox renders one flat list.
// Compose Popover + Command for headings.
<Command>
<CommandInput placeholder="Search..." />
<CommandList>
<CommandGroup heading="Production">
<CommandItem value="prod-us">
Production US
</CommandItem>
</CommandGroup>
</CommandList>
</Command>// Options take no icon. Compose
// Popover + Command for option icons.
<CommandItem value="datasets">
<Database className="text-muted-foreground" />
<span className="truncate">Datasets</span>
</CommandItem>const models = [
{ value: "sol", label: "Sol",
tag: <Badge variant="secondary" size="sm">New</Badge> },
{ value: "lyra", label: "Lyra", disabled: true },
];
<Combobox options={models} /><Combobox
options={regions}
size="sm"
icon={<Globe className="size-3.5" />}
/><Combobox options={[]} isLoading />Default, with tags, small with a trigger icon, and loading use the Combobox API. Combobox renders one flat list with no option icons, so the grouped and icon examples compose Popover and Command directly.
States
Default. Resting trigger, nothing selected.
Selected. The trigger shows the chosen label.
Disabled. Dimmed; the list cannot open.
Open. The list drops with the search input focused.
Searching. Typing narrows the list to matches.
Empty. No option matches the query.
Open, searching, and empty are interaction states. The open, searching, and empty cells render the underlying Command list inline so each is visible at rest.
API
Don't and Do
Don't reach for a Combobox when the option list is short and fixed. A handful of choices the reader can scan at a glance does not benefit from a search field, and the extra step to type slows them down. Use a Select instead.
<Combobox
options={timezones}
placeholder="Select a timezone..."
onValueChange={setZone}
/>Use it once the list is long enough that filtering meaningfully reduces the work of finding the right option.
import { Combobox } from "@/components/combobox";
const regions = [
{ value: "us-east", label: "US East (Virginia)" },
{ value: "eu-west", label: "EU West (Ireland)" },
// ...a long list worth filtering
];
export function RegionPicker() {
return (
<Combobox
options={regions}
placeholder="Select a region..."
searchPlaceholder="Search regions..."
/>
);
}