Jone

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 the Field component. See Labeling a combobox and the forms guide.

Anatomy

Import the components and place them together:

Anatomy
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:

Specifying generic type parameters
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.

Country

Use the Field component to provide a visible label for the combobox trigger:

Using Field to label a combobox
<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.

Example
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

NameTypeDefaultDescription
childrenOptionalReact.ReactNode | ((selectedValue: any) => React.ReactNode)
placeholderOptionalReact.ReactNodeThe 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

NameTypeDefaultDescription
disabledOptionalboolean | undefinedfalseWhether the component should ignore user interaction.

Clear

NameTypeDefaultDescription
disabledOptionalboolean | undefinedfalseWhether the component should ignore user interaction.
keepMountedOptionalboolean | undefinedfalseWhether the component should remain mounted in the DOM when not visible.

Trigger

NameTypeDefaultDescription
disabledOptionalboolean | undefinedfalseWhether the component should ignore user interaction.

List

NameTypeDefaultDescription
childrenOptionalReact.ReactNode | ((item: any, index: number) => React.ReactNode)

Portal

NameTypeDefaultDescription
keepMountedOptionalboolean | undefinedfalseWhether to keep the portal mounted in the DOM while the popup is hidden.

Collection

NameTypeDefaultDescription
childrenRequired(item: any, index: number) => React.ReactNode

Item

NameTypeDefaultDescription
childrenOptionalReact.ReactNode
onClickOptionalBaseUIComponentProps<'div', ComboboxItemState>['onClick'] | undefinedAn 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.
indexOptionalnumber | undefinedThe index of the item in the list. Improves performance when specified by avoiding the need to calculate the index automatically from the DOM.
valueOptionalanynullA unique value that identifies this item.
disabledOptionalboolean | undefinedfalseWhether the component should ignore user interaction.

ItemIndicator

NameTypeDefaultDescription
childrenOptionalReact.ReactNode
keepMountedOptionalboolean | undefinedfalseWhether to keep the HTML element in the DOM when the item is not selected.

Group

NameTypeDefaultDescription
itemsOptionalreadonly any[] | undefinedItems 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:

NameTypeDefaultDescription
localeIntl.LocalesArgumentThe locale to use for string comparison.
multiplebooleanfalseWhether the combobox is in multiple selection mode.
valueanyThe 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

PropertyTypeDescription
contains(itemValue: any, query: string, itemToString?: (itemValue) => string) => booleanReturns whether the item matches the query anywhere.
startsWith(itemValue: any, query: string, itemToString?: (itemValue) => string) => booleanReturns whether the item starts with the query.
endsWith(itemValue: any, query: string, itemToString?: (itemValue) => string) => booleanReturns whether the item ends with the query.

useFilteredItems

Returns the internally filtered items when called inside <Combobox.Root>.

Return value

PropertyTypeDescription
filteredItemsany[]The filtered items.

On this page