Combobox
A high-quality, unstyled React combobox component that renders an input combined with a list of predefined items to select.
An input combined with a list of predefined items to select.
Usage guidelines
- Combobox is a filterable Select: Use Combobox when the input is restricted to a set of predefined selectable items, similar to Select but whose items are filterable using an input. Prefer using Combobox over Select when the number of items is sufficiently large to warrant filtering.
- Avoid for simple search widgets: Combobox does not allow free-form text input. For search widgets, consider using Autocomplete instead.
- Avoid when not rendering an input: Use Select instead of Combobox if no input is being rendered, which includes accessibility features specific to a listbox without an input.
- Form controls must have an accessible name: It can be created using a
<label>element or theFieldcomponent. See Labeling a combobox and the forms guide.
Anatomy
Import the components and place them together:
import { Combobox } from '@base-ui/react/combobox';
<Combobox.Root>
<Combobox.Input />
<Combobox.Trigger />
<Combobox.Icon />
<Combobox.Clear />
<Combobox.Value />
<Combobox.Chips>
<Combobox.Chip>
<Combobox.ChipRemove />
</Combobox.Chip>
</Combobox.Chips>
<Combobox.Portal>
<Combobox.Backdrop />
<Combobox.Positioner>
<Combobox.Popup>
<Combobox.Arrow />
<Combobox.Status />
<Combobox.Empty />
<Combobox.List>
<Combobox.Row>
<Combobox.Item>
<Combobox.ItemIndicator />
</Combobox.Item>
</Combobox.Row>
<Combobox.Separator />
<Combobox.Group>
<Combobox.GroupLabel />
</Combobox.Group>
<Combobox.Collection />
</Combobox.List>
</Combobox.Popup>
</Combobox.Positioner>
</Combobox.Portal>
</Combobox.Root>;TypeScript
Combobox infers the item type from the defaultValue or value props passed to <Combobox.Root>.
The type of items held in the items array must also match the value prop type passed to <Combobox.Item>.
Examples
Typed wrapper component
The following example shows a typed wrapper around the Combobox component with correct type inference and type safety:
import * as React from 'react';
import { Combobox } from '@base-ui/react/combobox';
export function MyCombobox<Value, Multiple extends boolean | undefined = false>(
props: Combobox.Root.Props<Value, Multiple>,
): React.JSX.Element {
return <Combobox.Root {...props}>{/* ... */}</Combobox.Root>;
}Multiple select
The combobox can allow multiple selections by adding the multiple prop to <Combobox.Root>.
Selection chips are rendered with <Combobox.Chip> inside the input that can be removed.
Input inside popup
<Combobox.Input> can be rendered inside <Combobox.Popup> to create a searchable select popup.
Use the Field component to provide a visible label for the combobox trigger:
<Field.Root>
<Field.Label nativeLabel={false} render={<div />}>
Favorite fruit
</Field.Label>
<Combobox.Root>{/* ... */}</Combobox.Root>
</Field.Root>Replace the rendered <label> element with a <div> element and add nativeLabel={false} so it does not inherit native label behaviors. This ensures clicking on the label will focus the combobox trigger without opening the associated popup to match native <select> behavior, and prevents CSS :hover from activating on the trigger when hovering over the label.
Grouped
Organize related options with <Combobox.Group> and <Combobox.GroupLabel> to add section headings inside the popup.
Groups are represented by an array of objects with an items property, which itself is an array of individual items for each group. An extra property, such as value, can be provided for the heading text when rendering the group label.
interface ProduceGroupItem {
value: string;
items: string[];
}
const groups: ProduceGroupItem[] = [
{
value: 'Fruits',
items: ['Apple', 'Banana', 'Orange'],
},
{
value: 'Vegetables',
items: ['Carrot', 'Lettuce', 'Spinach'],
},
];Async search (single)
Load items from a remote source by fetching on input changes. Keep the selected item in the items list so it remains available while new results stream in. This pattern avoids needing to load items upfront.
Async search (multiple)
Load items from a remote source by fetching on input changes while supporting multiple selections. Selected items remain available in the list while new matches stream in. This pattern avoids needing to load items upfront.
Creatable
Create a new item when the filter matches no items, opening a creation <Dialog>.
Virtualized
Efficiently handle large datasets using a virtualization library like @tanstack/react-virtual.
API reference
Value
| Name | Type | Default | Description |
|---|---|---|---|
childrenOptional | React.ReactNode | ((selectedValue: any) => React.ReactNode) | — | — |
placeholderOptional | React.ReactNode | — | The placeholder value to display when no value is selected. This is overridden by `children` if specified, or by a null item's label in `items`. |
Input
| Name | Type | Default | Description |
|---|---|---|---|
disabledOptional | boolean | undefined | false | Whether the component should ignore user interaction. |
Clear
| Name | Type | Default | Description |
|---|---|---|---|
disabledOptional | boolean | undefined | false | Whether the component should ignore user interaction. |
keepMountedOptional | boolean | undefined | false | Whether the component should remain mounted in the DOM when not visible. |
Trigger
| Name | Type | Default | Description |
|---|---|---|---|
disabledOptional | boolean | undefined | false | Whether the component should ignore user interaction. |
List
| Name | Type | Default | Description |
|---|---|---|---|
childrenOptional | React.ReactNode | ((item: any, index: number) => React.ReactNode) | — | — |
Portal
| Name | Type | Default | Description |
|---|---|---|---|
keepMountedOptional | boolean | undefined | false | Whether to keep the portal mounted in the DOM while the popup is hidden. |
Collection
| Name | Type | Default | Description |
|---|---|---|---|
childrenRequired | (item: any, index: number) => React.ReactNode | — | — |
Item
| Name | Type | Default | Description |
|---|---|---|---|
childrenOptional | React.ReactNode | — | — |
onClickOptional | BaseUIComponentProps<'div', ComboboxItemState>['onClick'] | undefined | — | An optional click handler for the item when selected. It fires when clicking the item with the pointer, as well as when pressing `Enter` with the keyboard if the item is highlighted when the `Input` or `List` element has focus. |
indexOptional | number | undefined | — | The index of the item in the list. Improves performance when specified by avoiding the need to calculate the index automatically from the DOM. |
valueOptional | any | null | A unique value that identifies this item. |
disabledOptional | boolean | undefined | false | Whether the component should ignore user interaction. |
ItemIndicator
| Name | Type | Default | Description |
|---|---|---|---|
childrenOptional | React.ReactNode | — | — |
keepMountedOptional | boolean | undefined | false | Whether to keep the HTML element in the DOM when the item is not selected. |
Group
| Name | Type | Default | Description |
|---|---|---|---|
itemsOptional | readonly any[] | undefined | — | Items to be rendered within this group. When provided, child `Collection` components will use these items. |
useFilter
Matches items against a query using Intl.Collator for robust string matching.
This hook is used when externally filtering items.
Pass the result to the filter prop of <Combobox.Root>.
Input parameters
Accepts all Intl.CollatorOptions, plus the following options:
| Name | Type | Default | Description |
|---|---|---|---|
locale | Intl.LocalesArgument | — | The locale to use for string comparison. |
multiple | boolean | false | Whether the combobox is in multiple selection mode. |
value | any | — | The current value of the combobox. For single selection, pass this so all items are visible when the query is empty or matches the selection. |
Return value
| Property | Type | Description |
|---|---|---|
contains | (itemValue: any, query: string, itemToString?: (itemValue) => string) => boolean | Returns whether the item matches the query anywhere. |
startsWith | (itemValue: any, query: string, itemToString?: (itemValue) => string) => boolean | Returns whether the item starts with the query. |
endsWith | (itemValue: any, query: string, itemToString?: (itemValue) => string) => boolean | Returns whether the item ends with the query. |
useFilteredItems
Returns the internally filtered items when called inside <Combobox.Root>.
Return value
| Property | Type | Description |
|---|---|---|
filteredItems | any[] | The filtered items. |