The Combobox component combines a text input with a dropdown list, allowing users to search, filter, and select from predefined options.
Installation
npx shadcn@latest add @eo-n/combobox
Install dependencies
Install the required packages:npm install @base-ui/react lucide-react
Copy component code
Copy and paste the combobox component code into your project at components/ui/combobox.tsx.
Update imports
Update the import paths to match your project setup.
import {
Combobox,
ComboboxContent,
ComboboxEmpty,
ComboboxInput,
ComboboxItem,
ComboboxList,
} from "@/components/ui/combobox";
interface Fruit {
id: string;
value: string;
}
const fruits: Fruit[] = [
{ id: "a", value: "Apple" },
{ id: "b", value: "Banana" },
{ id: "c", value: "Cherry" },
{ id: "d", value: "Durian" },
];
export default function Example() {
return (
<Combobox items={fruits}>
<ComboboxInput placeholder="Search fruits..." />
<ComboboxContent>
<ComboboxEmpty>No fruits found.</ComboboxEmpty>
<ComboboxList>
{(fruit: Fruit) => (
<ComboboxItem key={fruit.id} value={fruit}>
{fruit.value}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>
);
}
Examples
Default
<Combobox items={fruits}>
<ComboboxInput placeholder="Select a fruit..." />
<ComboboxContent>
<ComboboxEmpty>No results found.</ComboboxEmpty>
<ComboboxList>
{(fruit: Fruit) => (
<ComboboxItem key={fruit.id} value={fruit}>
{fruit.value}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>
Multi-Select
import { ComboboxChips, ComboboxChip } from "@/components/ui/combobox";
<Combobox items={fruits} selectionBehavior="preserve">
<ComboboxChips>
{(fruit: Fruit) => (
<ComboboxChip key={fruit.id}>{fruit.value}</ComboboxChip>
)}
<ComboboxInput placeholder="Select fruits..." />
</ComboboxChips>
<ComboboxContent>
<ComboboxEmpty>No fruits found.</ComboboxEmpty>
<ComboboxList>
{(fruit: Fruit) => (
<ComboboxItem key={fruit.id} value={fruit}>
{fruit.value}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>
import { ComboboxTrigger } from "@/components/ui/combobox";
<Combobox items={fruits}>
<ComboboxTrigger>
<Button variant="outline">Select fruit</Button>
</ComboboxTrigger>
<ComboboxContent>
<ComboboxInput placeholder="Search..." />
<ComboboxEmpty>No results found.</ComboboxEmpty>
<ComboboxList>
{(fruit: Fruit) => (
<ComboboxItem key={fruit.id} value={fruit}>
{fruit.value}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>
With Groups
import { ComboboxGroup, ComboboxGroupLabel } from "@/components/ui/combobox";
<Combobox items={items}>
<ComboboxInput placeholder="Search..." />
<ComboboxContent>
<ComboboxEmpty>No results found.</ComboboxEmpty>
<ComboboxList>
<ComboboxGroup>
<ComboboxGroupLabel>Fruits</ComboboxGroupLabel>
{fruits.map((fruit) => (
<ComboboxItem key={fruit.id} value={fruit}>
{fruit.value}
</ComboboxItem>
))}
</ComboboxGroup>
<ComboboxGroup>
<ComboboxGroupLabel>Vegetables</ComboboxGroupLabel>
{vegetables.map((veg) => (
<ComboboxItem key={veg.id} value={veg}>
{veg.value}
</ComboboxItem>
))}
</ComboboxGroup>
</ComboboxList>
</ComboboxContent>
</Combobox>
Creatable
Allow users to create new items.
import { useState } from "react";
function CreatableCombobox() {
const [items, setItems] = useState(fruits);
const [value, setValue] = useState("");
const handleCreate = () => {
if (value && !items.find((item) => item.value === value)) {
setItems([...items, { id: crypto.randomUUID(), value }]);
}
};
return (
<Combobox items={items}>
<ComboboxInput
placeholder="Type to create..."
value={value}
onValueChange={setValue}
/>
<ComboboxContent>
<ComboboxEmpty>
<Button onClick={handleCreate}>Create "{value}"</Button>
</ComboboxEmpty>
<ComboboxList>
{(item: Fruit) => (
<ComboboxItem key={item.id} value={item}>
{item.value}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>
);
}
With Clear Button
import { ComboboxClear } from "@/components/ui/combobox";
import { X } from "lucide-react";
<Combobox items={fruits}>
<div className="relative">
<ComboboxInput placeholder="Search..." />
<ComboboxClear className="absolute right-2 top-2">
<X className="size-4" />
</ComboboxClear>
</div>
<ComboboxContent>
<ComboboxList>
{(fruit: Fruit) => (
<ComboboxItem key={fruit.id} value={fruit}>
{fruit.value}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>
API Reference
Combobox
Extends all props from @base-ui/react Combobox.Root component.
Array of items for the combobox.
The controlled selected value.
The default selected value when uncontrolled.
Callback fired when the selected value changes.
How selections are handled.Options: replace | preserve
Callback when open state changes.
ComboboxInput
Placeholder text for the input.
Callback when input value changes.
Additional CSS classes to apply.
ComboboxContent
Distance in pixels from the anchor.
Additional CSS classes to apply.
ComboboxItem
Whether the item is disabled.
Additional CSS classes to apply.
ComboboxList
Container for combobox items with virtualization support.
ComboboxEmpty
Displayed when no items match the search.
ComboboxChips
Container for selected items in multi-select mode.
ComboboxChip
Represents a selected item with a remove button.
ComboboxGroup
Groups related items together.
ComboboxGroupLabel
Label for a group of items.
TypeScript
import { Combobox as ComboboxPrimitive } from "@base-ui/react";
const Combobox = ComboboxPrimitive.Root;
type ComboboxInputProps = React.ComponentProps<typeof ComboboxPrimitive.Input>;
type ComboboxItemProps = React.ComponentProps<typeof ComboboxPrimitive.Item>;
Accessibility
- Keyboard navigation (Arrow keys, Enter, Escape)
- Proper ARIA attributes
- Screen reader support
- Focus management
- Type-ahead search
Related