Select
A dropdown for picking one option, wrapping the Base UI Select. Full keyboard navigation and typeahead come from the foundation; the popup opens with a small fade and settle.
Playground
Every control maps to a prop. The Code tab always shows the markup for exactly what you've configured.
Variants
Bordered is the default; borderless trades the border for a muted fill, the same surface as a secondary button.
States
Open, highlighted, and selected are live; try the examples. Disabled and invalid are the ones you set, and invalid turns the border and hint to the danger color.
Styling states
The highlighted item carries data-highlighted, the chosen one data-selected, and the trigger data-popup-open while open, so custom styling never needs JavaScript:
.ub-select-item[data-highlighted] {
background: var(--ub-bg-muted);
}Props
Each part passes the full Base UI API through. The essentials:
| Prop | Type | Default | Description |
|---|---|---|---|
SelectRoot.defaultValue | string | – | The option selected on first render, when uncontrolled. |
SelectRoot.value | string | – | Controlled selection. Pair with onValueChange. |
SelectRoot.onValueChange | (value) => void | – | Called when the selection changes. |
SelectTrigger.placeholder | ReactNode | – | Shown while nothing is selected. |
SelectTrigger.variant | "default" | "borderless" | "default" | Bordered, or a muted fill with no border. |
SelectRoot.items | Record<value, label> | – | Value to label map; required for the trigger to show the selected label before the dropdown has opened. |
SelectRoot.size | "default" | "compact" | "default" | Sizes the trigger and dropdown items together: 36px tall with 16px text by default, 28px with 14px text compact. |
SelectTrigger.disabled | boolean | false | Blocks opening the select. |
SelectTrigger.invalid | boolean | false | Danger border, ring, and hint, plus aria-invalid; a surrounding Field sets it automatically. |
SelectTrigger.leadingIcon | ReactNode | – | Icon before the value. Decorative. |
SelectTrigger.hint | ReactNode | – | Helper text below the trigger, linked via aria-describedby. |
SelectItem.value | string | – | Identity of the option. |
SelectItem.disabled | boolean | false | Blocks choosing this option. |
SelectContent.side | PositionerSide | – | Which side of the trigger the popup opens on; below by default. Also align. |
SelectContent.sideOffset | number | 4 | Gap between the trigger and the popup, in pixels. |
Agent instructions
Working with a coding agent? Paste this into its context, or point it at llms.txt for the whole library.
SelectRoot, SelectTrigger, SelectContent, SelectItem, from @usebones/react.
- SelectRoot: defaultValue or value + onValueChange (the callback value can be null); size sizes the trigger and dropdown items together. Always pass items (a value to label record) so the trigger shows the selected label instead of the raw value.
- SelectTrigger: placeholder, variant "default" | "borderless", invalid, leadingIcon, hint. The chevron renders automatically; there is no trailing icon slot.
- SelectContent handles the portal and positioning. SelectItem children are the label; the selected check renders automatically.
- Inside FieldRoot, drop invalid and hint and use FieldLabel, FieldDescription, and FieldError instead.
- Restyle in CSS via .ub-select-trigger, .ub-select-popup, .ub-select-item, [data-highlighted], [data-selected], [data-popup-open]. Tokens only.