Combobox
A picker with search. Single or multiple, with checkboxes for multiple.
import { Combobox } from "@openperf/deft";
import { Preview } from "../../src/Preview";
export default function ComboboxBasic() {
return (
<Preview overlay={true}>
<Combobox.Root
defaultValue="Option 1"
items={["Option 1", "Option 2", "Option 3", "Option 4"]}
>
<Combobox.Trigger>
<Combobox.Value />
</Combobox.Trigger>
<Combobox.Content>
<Combobox.Search placeholder="Search" />
<Combobox.Empty>No results</Combobox.Empty>
<Combobox.List>
{(option: string) => (
<Combobox.Item key={option} value={option}>
{option}
</Combobox.Item>
)}
</Combobox.List>
</Combobox.Content>
</Combobox.Root>
</Preview>
);
}
- Use a combobox when the list is long enough to need search, such as projects. For a short fixed list, use a Select; for actions, a Menu.
- Search takes focus on open, and
Combobox.Emptynames what was not found. - A single-select combobox marks the current value with a check.
- The trigger is a button and takes its
variantandsize, with a chevron after the label.
Multiple select
import { Button, Combobox } from "@openperf/deft";
import { IconPlus } from "@tabler/icons-react";
import { useState } from "react";
import { Preview } from "../../src/Preview";
interface Option {
count: number;
label: string;
}
const OPTIONS: Option[] = [
{ label: "Option 1", count: 120 },
{ label: "Option 2", count: 48 },
{ label: "Option 3", count: 12 },
];
export default function ComboboxMultipleSelect() {
const [value, setValue] = useState<Option[]>([]);
return (
<Preview overlay={true}>
<Combobox.Root
items={OPTIONS}
itemToStringLabel={(option: Option) => option.label}
multiple={true}
onValueChange={setValue}
value={value}
>
<Combobox.Trigger>
{value.length > 0 ? value.map((option) => option.label).join(", ") : "Select options"}
</Combobox.Trigger>
<Combobox.Content>
<Combobox.Search placeholder="Search" />
<Combobox.Empty>No results</Combobox.Empty>
<Combobox.List>
{(option: Option) => (
<Combobox.Item
icon={IconPlus}
indicator="checkbox"
key={option.label}
trailing={option.count}
value={option}
>
{option.label}
</Combobox.Item>
)}
</Combobox.List>
<Combobox.Footer>
<Button.Root
onClick={() => {
setValue([]);
}}
size="sm"
variant="ghost"
>
Clear
</Button.Root>
</Combobox.Footer>
</Combobox.Content>
</Combobox.Root>
</Preview>
);
}
Set multiple on Root and indicator="checkbox" on each item, and show the selected labels in the trigger. icon leads an item and trailing adds a value after its label, such as a count that helps people choose. Combobox.Footer holds actions for the whole list, such as a reset.
API
PropType
variant?"default" | "field" | "primary" | "ghost" | "danger"
On Trigger.
Type
"default" | "field" | "primary" | "ghost" | "danger"Default
"default"size?"inline" | "xs" | "sm" | "md"
On Trigger.
Type
"inline" | "xs" | "sm" | "md"Default
"md"align?"start" | "center" | "end"
On Content.
Type
"start" | "center" | "end"Default
"start"indicator?"check" | "checkbox"
On Item.
Type
"check" | "checkbox"Default
"check"icon?Icon
On Item. A Tabler icon before the label.
Type
Icontrailing?ReactNode
On Item. After the label.
Type
ReactNodeParts: Root, Content, Empty, Footer, GroupLabel, Item, List, Search, Trigger, and the other Base UI parts, such as Value and Group. Content renders the portal, positioner and popup; Search renders Base UI’s Input. Built on Base UI Combobox.