Components
Component
productdevbook/ui

Stable in React

Combobox

An input combined with a list of predefined items to select.

Loading React 19.3.1…
Hover a part or use it. The code follows. · Loading React…
2,150Tests passing in React · 0 failing
63.5 KiBSize
5.20 msOpen
2.50 msClose
0.99 MiBMemory
productdevbook and 40 upstream authors23 commits · last

Install#

One package per framework. Combobox's parts come from it; the anatomy tab at the top shows how they nest.

bun add @▢▢▢▢/react

26 parts. The example uses 14 of them; the data does not say which are required.

  • Combobox.RootGroups all parts of the combobox.
  • Combobox.InputGroupA wrapper for the input and its associated controls.
  • Combobox.InputA text input to search for items in the list.
  • Combobox.ClearClears the value when clicked.
  • Combobox.TriggerA button that opens the popup.
  • Combobox.IconAn icon that indicates that the trigger button opens the popup.
  • Combobox.PortalA portal element that moves the popup to a different part of the DOM.
  • Combobox.PositionerPositions the popup against the trigger.
  • Combobox.PopupA container for the list.
  • Combobox.EmptyRenders its children only when the list is empty.
  • Combobox.ListA list container for the items.
  • Combobox.CollectionRenders filtered list items.
  • Combobox.ItemAn individual item in the list.
  • Combobox.ItemIndicatorIndicates whether the item is selected.
  • Combobox.ArrowDisplays an element positioned against the anchor. Not in the example.
  • Combobox.BackdropAn overlay displayed beneath the popup. Not in the example.
  • Combobox.ChipAn individual chip that represents a value in a multiselectable input. Not in the example.
  • Combobox.ChipRemoveA button to remove a chip. Not in the example.
  • Combobox.ChipsA container for the chips in a multiselectable input. Not in the example.
  • Combobox.GroupGroups related items with the corresponding label. Not in the example.
  • Combobox.GroupLabelAn accessible label that is automatically associated with its parent group. Not in the example.
  • Combobox.LabelAn accessible label that is automatically associated with the combobox trigger. Not in the example.
  • Combobox.RowDisplays a single row of items in a grid list. Not in the example.
  • Combobox.SeparatorA visual separator between items or groups. Not in the example.
  • Combobox.StatusDisplays a status message whose content changes are announced politely to screen readers. Not in the example.
  • Combobox.ValueThe current value of the combobox. Not in the example.

Examples#

Common ways to put it to work. Each one runs live.

createItems derives each item's value and label when the app stores ids.

ComboboxCreateItems.tsx

Styling and accessibility#

The parts ship no styles. Style their states with these attributes; the CSS tab at the top has a sheet. The same CSS works in all five frameworks.

  • [data-popup-open]Present when the corresponding popup is open. On InputGroup, Input, Clear, Trigger.
  • [data-pressed]Present when the input group is pressed. On InputGroup, Input, Trigger.
  • [data-disabled]Present when the component is disabled. On InputGroup, Input, Clear, Trigger, Item.
  • [data-readonly]Present when the component is readonly. On InputGroup, Input, Trigger.
  • [data-popup-side]Indicates which side the corresponding popup is positioned relative to its anchor. On InputGroup, Input, Trigger.
  • [data-valid]Present when the component is in a valid state (when wrapped in Field.Root). On InputGroup, Input, Trigger.
  • [data-invalid]Present when the component is in an invalid state (when wrapped in Field.Root). On InputGroup, Input, Trigger.
  • [data-touched]Present when the component has been touched (when wrapped in Field.Root). On InputGroup, Input, Trigger.
  • [data-dirty]Present when the component's value has changed (when wrapped in Field.Root). On InputGroup, Input, Trigger.
  • [data-filled]Present when the component has a value (when wrapped in Field.Root). On InputGroup, Input, Trigger.
  • [data-focused]Present when the component is focused (when wrapped in Field.Root). On InputGroup, Input, Trigger.
  • [data-list-empty]Present when the corresponding items list is empty. On InputGroup, Input, Trigger.
  • [data-placeholder]Present when the combobox doesn't have a value. On InputGroup, Trigger.
  • [data-required]Present when the component is required. On Input, Trigger.
  • [data-visible]Present when the clear button is visible. On Clear.
  • [data-starting-style]Present when the button begins animating in. On Clear, Popup, ItemIndicator, Backdrop.
  • [data-ending-style]Present when the button is animating out. On Clear, Popup, ItemIndicator, Backdrop.
  • [data-open]Present when the popup is open. On Positioner, Popup, Arrow, Backdrop.
  • [data-closed]Present when the popup is closed. On Positioner, Popup, Arrow, Backdrop.
  • [data-anchor-hidden]Present when the anchor is hidden. On Positioner, Popup.
  • [data-side]Indicates which side the popup is positioned relative to the trigger. On Positioner, Popup, Arrow.
  • [data-align]Indicates how the popup is aligned relative to specified side. On Positioner, Popup, Arrow.
  • [data-empty]Present when the items list is empty. On Positioner, Popup.
  • --available-widthThe available width between the trigger and the edge of the viewport. On Positioner.
  • --available-heightThe available height between the trigger and the edge of the viewport. On Positioner.
  • --anchor-widthThe anchor's width. On Positioner.
  • --anchor-heightThe anchor's height. On Positioner.
  • --transform-originThe coordinates that this element is anchored to. Used for animations and transitions. On Positioner.
  • [data-selected]Present when the item is selected. On Item.
  • [data-highlighted]Present when the item is highlighted. On Item.
  • [data-uncentered]Present when the arrow is uncentered. On Arrow.
  • [data-orientation]Indicates the orientation of the separator. On Separator.

Keyboard

  • ArrowDownArrowUpOpens the list and highlights the first or the last item On Input.
  • ArrowDownArrowUpMoves the highlight and wraps at the ends while loopFocus is on On List.
  • ArrowDownArrowUpArrowLeftArrowRightWith grid, moves across rows and columns On Row.
  • EnterSelects the highlighted item On Item.
  • EscapeCloses the list without changing the value On Input.
  • EscapeWith the list closed and multiple on, clears the selected values On Input.
  • TabCloses the list without changing the value and moves focus on On Input.
  • BackspaceIn an empty input, removes the last chip On Input.
  • ArrowLeftArrowRightMoves between chips and back to the input On Chip.
  • DeleteRemoves the focused chip On Chip.
  • ArrowDownArrowUpOpens the list from the trigger On Trigger.

Set for you

  • role="combobox", aria-expanded, aria-haspopup, aria-controls to the list while opena screen reader says the input picks from a list and whether it is shownInput
  • aria-autocomplete, aria-activedescendant to the highlighted itemthe highlight is read while focus stays in the inputInput
  • aria-haspopup ("listbox", or "dialog" when the input is inside the popup), aria-expandedthe button says what it opensTrigger
  • role="listbox" (role="grid" with grid), aria-multiselectable with multiplethe items are announced as options, and whether several can be chosenList
  • role="option" (role="gridcell" in a Row), aria-selectedeach item is read with its selected stateItem
  • role="row"grid rows are announced as rowsRow
  • role="toolbar"the chips are one group the arrow keys move throughChips
  • aria-labelledby to its GroupLabela group of items is read with its headingGroup
  • role="status", aria-live="polite"loading and result counts are announced without moving focusStatus
  • role="status", aria-live="polite""no results" is announced as it appearsEmpty
  • aria-hidden="true"the decorative icon is not readIcon

API reference#

75 props across 26 parts, in React syntax, and className, style, render once for every part. Open a row to try it.

Combobox · all parts
Shared propsEvery part that renders an element takes these.
classNameCSS class applied to the element, or a function that returns a class based on the component's state.string | ((state: State) => string | undefined)
styleStyle applied to the element, or a function that returns a style object based on the component's state.React.CSSProperties | ((state: State) => React.CSSProperties | undefined)
renderAllows you to replace the component's HTML element with a different tag, or compose it with another component.React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, State>

Use it in React#

What differs from the React API. Switch the framework at the top of the page.

@▢▢▢▢/react is the React 19 package. Its parts, props, data attributes and error messages are upstream Base UI's, and upstream's own tests run against it.

  • Parts

    Each component is its own entry point and exports one namespace named after it.

    import { Switch } from '@base-ui-next/react/switch'
    
    export function Example() {
      return (
        <Switch.Root>
          <Switch.Thumb />
        </Switch.Root>
      )
    }

    A part renders the element its API reference names, such as a <span> for Switch.Root.

  • Props and events

    Props and callbacks have upstream's names and signatures: onCheckedChange(checked, details), onOpenChange(open, details), onValueChange(value, details). details carries reason, event, cancel() and allowPropagation(). Native handlers are React's (onClick, onKeyDown), and event.preventBaseUIHandler() stops a part's own handler.

  • Styling

    className takes a string or a function (state) => string; style takes an object or a function (state) => object. The state's data-* attributes are on the element for CSS.

  • render

    render takes an element (render={<a href="/docs" />}) or a function (props, state) => element that spreads props on what it returns.

  • Refs

    ref reaches the part's element. Imperative handles are ref props, as upstream: inputRef, and actionsRef ({ validate } on Field and Form, { unmount, close } on Dialog).

  • Binding

    A part is controlled when its value prop (checked, open, value) is set, and uncontrolled with the default form (defaultChecked, defaultOpen, defaultValue). React has no two-way binding: pair the value with its change callback.

  • From @base-ui/react
    Change the import from @base-ui/react/<component> to @▢▢▢▢/react/<component>.
  • From @base-ui/react
    Nothing else changes: props, parts, data attributes and errors are the same.