Combobox

Comboboxes let users choose an option from a list they can filter by typing into a search field.

The Combobox component is a Base UI component.

The control is a ComboboxTrigger that shows the selected option with ComboboxValue, and the typing field lives inside the popup as ComboboxSearch. Pass the options to the items prop on Combobox and render each one with a ComboboxList render function, so the list is filtered as the user types. ComboboxEmpty renders its children when no options match.

const FONTS = ["Sans-serif", "Serif", "Monospace", "Cursive", "Fantasy", "System UI"]
return (
<Combobox items={FONTS}>
<ComboboxTrigger className="max-w-256">
<ComboboxValue placeholder="Select a font" />
</ComboboxTrigger>
<ComboboxContent>
<ComboboxSearch placeholder="Search fonts" />
<ComboboxEmpty>No fonts found.</ComboboxEmpty>
<ComboboxList>
{(font) => (
<ComboboxItem key={font} value={font}>
{font}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>
)

Groups

Use ComboboxGroup with a ComboboxGroupLabel to label related options. Represent the options as an array of group objects with an items property, pass each group's items to its ComboboxGroup, and render the options with ComboboxCollection so filtering keeps working. Groups without a matching option are hidden.

const FONT_GROUPS = [
{
items: ["Sans-serif", "Serif"],
value: "Proportional",
},
{
items: ["Monospace"],
value: "Fixed width",
},
]
return (
<Combobox items={FONT_GROUPS}>
<ComboboxTrigger className="max-w-256">
<ComboboxValue placeholder="Select a font" />
</ComboboxTrigger>
<ComboboxContent>
<ComboboxSearch placeholder="Search fonts" />
<ComboboxEmpty>No fonts found.</ComboboxEmpty>
<ComboboxList>
{(group) => (
<ComboboxGroup items={group.items} key={group.value}>
<ComboboxGroupLabel>{group.value}</ComboboxGroupLabel>
<ComboboxCollection>
{(font) => (
<ComboboxItem key={font} value={font}>
{font}
</ComboboxItem>
)}
</ComboboxCollection>
</ComboboxGroup>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>
)

Icons

Options can include an icon before their label and a supporting description. Pass a render function to ComboboxValue to render the selected option's icon and description in the control — like the Select.

Use option objects shaped as { value, label, ... }: the label is automatically used for filtering, and the value for form submission.

const MODELS = [
{
description: "Max",
icon: Claude.Color,
label: "Fable 5",
value: "fable-5",
},
{
description: "High Fast",
icon: Grok,
label: "Grok 4.5",
value: "grok-4.5",
},
{
description: "Medium",
icon: OpenAI,
label: "GPT-5.6 Sol",
value: "gpt-5.6-sol",
},
{
description: "Fast",
icon: Gemini.Color,
label: "Gemini 2.5 Pro",
value: "gemini-2.5-pro",
},
]
return (
<Combobox defaultValue={MODELS[0]} items={MODELS}>
<ComboboxTrigger className="max-w-288">
<ComboboxValue placeholder="Select a model">
{(model) => (
<Row className="items-center">
{model.icon && <model.icon className="mr-8" size={18} />}
<span className="truncate">{model.label}</span>
{model.description && (
<span className="text-13 text-gray-9 font-400 ml-6 truncate">
{model.description}
</span>
)}
</Row>
)}
</ComboboxValue>
</ComboboxTrigger>
<ComboboxContent>
<ComboboxSearch placeholder="Search models" />
<ComboboxEmpty>No models found.</ComboboxEmpty>
<ComboboxList>
{(model) => (
<ComboboxItem key={model.value} value={model}>
<Row className="items-center">
{model.icon && <model.icon className="mr-8" size={18} />}
<span className="truncate">{model.label}</span>
{model.description && (
<span className="text-13 text-gray-9 font-400 ml-6 truncate">
{model.description}
</span>
)}
</Row>
</ComboboxItem>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>
)

Size

The ComboboxTrigger comes with 5 sizes: 32, 36, 40 (default), 44, and 48.

<Combobox items={FONTS}>
<ComboboxTrigger size={32}>
<ComboboxValue placeholder="Size 32" />
</ComboboxTrigger>
<ComboboxContent>{/* ... */}</ComboboxContent>
</Combobox>
<Combobox items={FONTS}>
<ComboboxTrigger size={36}>
<ComboboxValue placeholder="Size 36" />
</ComboboxTrigger>
<ComboboxContent>{/* ... */}</ComboboxContent>
</Combobox>
<Combobox items={FONTS}>
<ComboboxTrigger size={40}>
<ComboboxValue placeholder="Size 40" />
</ComboboxTrigger>
<ComboboxContent>{/* ... */}</ComboboxContent>
</Combobox>
<Combobox items={FONTS}>
<ComboboxTrigger size={44}>
<ComboboxValue placeholder="Size 44" />
</ComboboxTrigger>
<ComboboxContent>{/* ... */}</ComboboxContent>
</Combobox>
<Combobox items={FONTS}>
<ComboboxTrigger size={48}>
<ComboboxValue placeholder="Size 48" />
</ComboboxTrigger>
<ComboboxContent>{/* ... */}</ComboboxContent>
</Combobox>

Rounded

Use the rounded prop to give the trigger fully rounded corners.

<Combobox items={FONTS}>
<ComboboxTrigger className="max-w-256" rounded>
<ComboboxValue placeholder="Select a font" />
</ComboboxTrigger>
<ComboboxContent>
<ComboboxSearch placeholder="Search fonts" />
<ComboboxEmpty>No fonts found.</ComboboxEmpty>
<ComboboxList>
{(font) => (
<ComboboxItem key={font} value={font}>
{font}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>

Disabled

Use the disabled prop on ComboboxItem to prevent a single option from being selected, or the disabled prop on Combobox to disable the entire control.

<Combobox items={FONTS}>
<ComboboxTrigger className="max-w-256">
<ComboboxValue placeholder="Select a font" />
</ComboboxTrigger>
<ComboboxContent>
<ComboboxSearch placeholder="Search fonts" />
<ComboboxEmpty>No fonts found.</ComboboxEmpty>
<ComboboxList>
{(font) => (
<ComboboxItem disabled={font === "Cursive"} key={font} value={font}>
{font}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>
<Combobox defaultValue="Sans-serif" disabled items={FONTS}>
<ComboboxTrigger className="max-w-256">
<ComboboxValue placeholder="Select a font" />
</ComboboxTrigger>
</Combobox>

State

By default, Combobox is an uncontrolled component that manages its own state. Use the defaultValue prop to set the initially selected option.

<Combobox defaultValue="Sans-serif" items={FONTS}>
<ComboboxTrigger>
<ComboboxValue placeholder="Select a font" />
</ComboboxTrigger>
<ComboboxContent>{/* ... */}</ComboboxContent>
</Combobox>

Use value and onValueChange props if you need to access or control the selected option. The text typed into ComboboxSearch can be controlled separately with the inputValue and onInputValueChange props.

const [font, setFont] = useState(null)
return (
<Combobox items={FONTS} onValueChange={setFont} value={font}>
<ComboboxTrigger>
<ComboboxValue placeholder="Select a font" />
</ComboboxTrigger>
<ComboboxContent>{/* ... */}</ComboboxContent>
</Combobox>
)