Combobox
An autocomplete input with a filterable dropdown list, built on Base UI’s Combobox primitive.
Usage
import {
Combobox,
ComboboxContent,
ComboboxEmpty,
ComboboxInput,
ComboboxItem,
ComboboxList,
} from "@/components/ui/combobox"Pass your items array to the items prop on Combobox and use a render function as the child of ComboboxList to render each item. This enables built-in filtering and the empty state.
const options = [
{ value: "option-1", label: "Option 1" },
{ value: "option-2", label: "Option 2" },
{ value: "option-3", label: "Option 3" },
]
<Combobox items={options}>
<ComboboxInput placeholder="Select an option..." className="w-56" />
<ComboboxContent>
<ComboboxEmpty>No results found.</ComboboxEmpty>
<ComboboxList>
{(item) => (
<ComboboxItem key={item.value} value={item.value}>{item.label}</ComboboxItem>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>Examples
Multiple
Enable multiple selection with chips using the multiple prop. Control the selection with value and onValueChange, then render chips from your state array. Use useComboboxAnchor so the popup aligns to the chips container.
import {
Combobox,
ComboboxChip,
ComboboxChips,
ComboboxChipsInput,
ComboboxContent,
ComboboxEmpty,
ComboboxItem,
ComboboxList,
useComboboxAnchor,
} from "@/components/ui/combobox"
const frameworks = [
{ value: "next.js", label: "Next.js" },
{ value: "remix", label: "Remix" },
]
export function MyCombobox() {
const anchor = useComboboxAnchor()
const [selected, setSelected] = React.useState<string[]>([])
return (
<Combobox multiple items={frameworks} value={selected} onValueChange={setSelected}>
<ComboboxChips ref={anchor} className="w-72">
{selected.map((v) => {
const item = frameworks.find((f) => f.value === v)
return <ComboboxChip key={v}>{item?.label ?? v}</ComboboxChip>
})}
<ComboboxChipsInput placeholder={selected.length === 0 ? "Select frameworks..." : ""} />
</ComboboxChips>
<ComboboxContent anchor={anchor}>
<ComboboxEmpty>No results found.</ComboboxEmpty>
<ComboboxList>
{(item) => (
<ComboboxItem key={item.value} value={item.value}>{item.label}</ComboboxItem>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>
)
}Clear button
Add showClear to ComboboxInput to display a clear button when a value is selected. The chevron is automatically hidden when the clear button is visible.
<Combobox items={frameworks}>
<ComboboxInput placeholder="Select a framework..." className="w-56" showClear />
<ComboboxContent>
<ComboboxEmpty>No results found.</ComboboxEmpty>
<ComboboxList>
{(item) => (
<ComboboxItem key={item.value} value={item.value}>{item.label}</ComboboxItem>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>Groups
Use ComboboxGroup with ComboboxLabel to organize items into labelled sections. Pass an array of { label, items } objects to the items prop and use a render function that returns a ComboboxGroup per group.
const groupedFrameworks = [
{ label: "React", items: [{ value: "next.js", label: "Next.js" }, { value: "remix", label: "Remix" }] },
{ label: "Vue", items: [{ value: "nuxt.js", label: "Nuxt.js" }] },
{ label: "Other", items: [{ value: "sveltekit", label: "SvelteKit" }, { value: "astro", label: "Astro" }] },
]
<Combobox items={groupedFrameworks}>
<ComboboxInput placeholder="Select a framework..." className="w-56" />
<ComboboxContent>
<ComboboxEmpty>No results found.</ComboboxEmpty>
<ComboboxList>
{(group) => (
<ComboboxGroup key={group.label}>
<ComboboxLabel>{group.label}</ComboboxLabel>
{group.items.map((item) => (
<ComboboxItem key={item.value} value={item.value}>{item.label}</ComboboxItem>
))}
</ComboboxGroup>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>Custom items
Compose ComboboxItem with icons, badges, or multi-line content to build richer option lists.
<ComboboxItem value="next.js" className="pr-8">
<GitBranchIcon />
<div className="flex flex-col">
<span className="font-medium">Next.js</span>
<span className="text-default-11 text-xs">React framework</span>
</div>
</ComboboxItem>Invalid and Disabled
{/* Invalid */}
<Field data-invalid="true">
<FieldLabel>Framework</FieldLabel>
<Combobox items={frameworks}>
<ComboboxInput placeholder="Select a framework..." aria-invalid="true" />
<ComboboxContent>
<ComboboxEmpty>No results found.</ComboboxEmpty>
<ComboboxList>
{(item) => (
<ComboboxItem key={item.value} value={item.value}>{item.label}</ComboboxItem>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>
<FieldError>Please select a framework.</FieldError>
</Field>
{/* Disabled */}
<Combobox disabled items={frameworks}>
<ComboboxInput placeholder="Select a framework..." disabled />
<ComboboxContent>
<ComboboxEmpty>No results found.</ComboboxEmpty>
<ComboboxList>
{(item) => (
<ComboboxItem key={item.value} value={item.value}>{item.label}</ComboboxItem>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>Auto-highlight
With autoHighlight, the first matching item is highlighted automatically as you type, so pressing Enter selects it immediately.
<Combobox autoHighlight items={frameworks}>
<ComboboxInput placeholder="Type to search..." className="w-56" />
<ComboboxContent>
<ComboboxEmpty>No results found.</ComboboxEmpty>
<ComboboxList>
{(item) => (
<ComboboxItem key={item.value} value={item.value}>{item.label}</ComboboxItem>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>Pop-up
In the pop-up pattern, a styled trigger button shows the selected value and clicking it opens a popup that contains both the search input and the list. Useful when you want a select-like appearance with search capability.
<Combobox items={frameworks}>
<ComboboxTrigger className="flex h-8 w-56 items-center justify-between gap-2 rounded-lg border bg-default-1 px-2.5 text-sm font-normal">
<ComboboxValue placeholder="Select a framework..." />
</ComboboxTrigger>
<ComboboxContent>
<ComboboxInput showTrigger={false} placeholder="Search..." autoFocus />
<ComboboxEmpty>No results found.</ComboboxEmpty>
<ComboboxList>
{(item) => (
<ComboboxItem key={item.value} value={item.value}>{item.label}</ComboboxItem>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>Input group
Pass an InputGroupAddon as a child of ComboboxInput to add a leading icon or prefix element.
import { InputGroupAddon } from "@/components/ui/input-group"
import { SearchIcon } from "lucide-react"
<Combobox items={frameworks}>
<ComboboxInput placeholder="Search frameworks..." className="w-64">
<InputGroupAddon align="inline-start">
<SearchIcon />
</InputGroupAddon>
</ComboboxInput>
<ComboboxContent>
<ComboboxEmpty>No results found.</ComboboxEmpty>
<ComboboxList>
{(item) => (
<ComboboxItem key={item.value} value={item.value}>{item.label}</ComboboxItem>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>