Components
Component
productdevbook/ui

Stable in React

Select

A common form control for choosing a predefined value in a dropdown.

Loading React 19.3.1…
Hover a part or use it. The code follows. · Loading React…
1,234Tests passing in React · 0 failing
55.9 KiBSize
2.50 msOpen
1.70 msClose
3.14 MiBMemory
productdevbook and 40 upstream authors17 commits · last

Install#

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

bun add @▢▢▢▢/react

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

  • Select.RootGroups all parts of the select.
  • Select.LabelAn accessible label that is automatically associated with the select trigger.
  • Select.TriggerA button that opens the select popup.
  • Select.ValueA text label of the currently selected item.
  • Select.IconAn icon that indicates that the trigger button opens a select popup.
  • Select.PortalA portal element that moves the popup to a different part of the DOM.
  • Select.PositionerPositions the select popup.
  • Select.PopupA container for the select list.
  • Select.ScrollUpArrowAn element that scrolls the select popup up when hovered.
  • Select.ListA container for the select items.
  • Select.ItemAn individual option in the select popup.
  • Select.ItemIndicatorIndicates whether the select item is selected.
  • Select.ItemTextA text label of the select item.
  • Select.ScrollDownArrowAn element that scrolls the select popup down when hovered.
  • Select.ArrowDisplays an element positioned against the select popup anchor. Not in the example.
  • Select.BackdropAn overlay displayed beneath the select popup. Not in the example.
  • Select.GroupGroups related select items with the corresponding label. Not in the example.
  • Select.GroupLabelAn accessible label that is automatically associated with its parent group. Not in the example.
  • Select.SeparatorA visual separator between items or groups. Not in the example.

Examples#

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

multiple keeps several values.

SelectMultiple.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 select is open. On Trigger, Icon.
  • [data-pressed]Present when the trigger is pressed. On Trigger.
  • [data-disabled]Present when the select is disabled. On Trigger, Item.
  • [data-readonly]Present when the select is readonly. On Trigger.
  • [data-popup-side]Indicates which side the corresponding popup is positioned relative to its anchor. On Trigger.
  • [data-required]Present when the select is required. On Trigger.
  • [data-valid]Present when the select is in a valid state (when wrapped in Field.Root). On Trigger.
  • [data-invalid]Present when the select is in an invalid state (when wrapped in Field.Root). On Trigger.
  • [data-touched]Present when the select has been touched (when wrapped in Field.Root). On Trigger.
  • [data-dirty]Present when the select's value has changed (when wrapped in Field.Root). On Trigger.
  • [data-filled]Present when the select has a value (when wrapped in Field.Root). On Trigger.
  • [data-focused]Present when the select trigger is focused (when wrapped in Field.Root). On Trigger.
  • [data-placeholder]Present when the select doesn't have a value. On Trigger, Value.
  • [data-open]Present when the select popup is open. On Positioner, Popup, Arrow, Backdrop.
  • [data-closed]Present when the select popup is closed. On Positioner, Popup, Arrow, Backdrop.
  • [data-anchor-hidden]Present when the anchor is hidden. On Positioner.
  • [data-side]Indicates which side the popup is positioned relative to the trigger. On Positioner, Popup, ScrollUpArrow, ScrollDownArrow, Arrow.
  • [data-align]Indicates how the popup is aligned relative to specified side. On Positioner, Popup, Arrow.
  • --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-starting-style]Present when the select begins animating in. On Popup, ScrollUpArrow, ItemIndicator, ScrollDownArrow, Backdrop.
  • [data-ending-style]Present when the select is animating out. On Popup, ScrollUpArrow, ItemIndicator, ScrollDownArrow, Backdrop.
  • [data-direction]Indicates the direction of the scroll arrow. On ScrollUpArrow, ScrollDownArrow.
  • [data-visible]Present when the scroll arrow is visible. On ScrollUpArrow, ScrollDownArrow.
  • [data-selected]Present when the select item is selected. On Item.
  • [data-highlighted]Present when the select item is highlighted. On Item.
  • [data-uncentered]Present when the select arrow is uncentered. On Arrow.
  • [data-orientation]Indicates the orientation of the separator. On Separator.

Keyboard

  • ArrowDownEnterSpaceOpens the popup On Trigger.
  • On the closed trigger, selects the next item whose text starts with what was typed On Trigger.
  • ArrowDownArrowUpMoves the highlight one item at a time and stops at the ends On List.
  • HomeEndMoves the highlight to the first or last item On List.
  • In the open popup, highlights the next item whose text starts with what was typed On List.
  • EnterSelects the highlighted item and closes the popup On Item.
  • EscapeCloses the popup without changing the value and keeps focus on the trigger On Popup.
  • TabCloses the popup without changing the value and moves on On Popup.

Set for you

  • role="combobox", aria-haspopup="listbox", aria-expanded, aria-controlsa screen reader says the button picks from a list and whether it is openTrigger
  • aria-labelledby to Label, aria-readonly, aria-requiredthe control is read with its name and constraintsTrigger
  • role="listbox", aria-multiselectable with multiplethe items are announced as options, and whether several can be chosenList
  • role="option", aria-selectedeach option is read with its selected stateItem
  • role="group", aria-labelledby to its GroupLabelgrouped options are read under their headingGroup
  • aria-hidden="true"the decorative chevron is not readIcon
  • aria-hidden="true"the scroll arrows are pointer aids onlyScrollUpArrow
  • aria-hidden="true"the scroll arrows are pointer aids onlyScrollDownArrow
  • role="presentation"the overlay is not readBackdrop

API reference#

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

Select · 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.