Select
This is a real, native <select>, styled to match the rest of the library. It is not a custom listbox built out of <div>s: every native behaviour (keyboard navigation, typeahead, mobile picker UI, form submission) comes from the browser for free.
Example (a11y tier)
Used to determine shipping options.
Select a plan to continue.
Import
import Select from 'abaabil/select' // structure onlyimport Select from 'abaabil/select/styled' // + CSSimport Select from 'abaabil/select/a11y' // + label/description/error wiringWhy a native <select>, not a custom listbox
Newer CSS (appearance: base-select) lets a native <select> have its open dropdown fully restyled, which would let this component look more like the combobox's popover while staying native. It was deliberately not used here: it is not yet Baseline, it ships only in Chrome 135+, with no Firefox support, which sits far above this library's already-stated browser floor (Chrome 116, Firefox 125, Safari 17). Styling only what the CSS spec already lets every supported browser style, the closed control itself, keeps this component working everywhere the rest of the library does, at the cost of the open dropdown still using each browser's own native rendering.
What the a11y tier adds
- Renders a real
<label>associated with the<select>viahtmlFor/id. - Joins whichever of
descriptionanderrorare present into onearia-describedby. - Sets
aria-invalidwhenerroris present. - Warns in development if
labelis omitted, since the platform gives a bare<select>no accessible name on its own.
Props
| Prop | Type | Default | Tier | Description |
|---|---|---|---|---|
options | Array<{value, label}> | — | all | Rendered as <option> elements. Omit and pass children directly for <optgroup> or custom option markup. |
children | ReactNode | — | all | Used only when options is not given. |
className | string | — | all | Merged with the base class. |
label | string | — | a11y | Accessible name, rendered as a real <label>. |
description | string | — | a11y | Rendered and wired into aria-describedby. |
error | string | — | a11y | Rendered, sets aria-invalid, joined into aria-describedby alongside the description. |
id | string | — | a11y | Explicit id for the select. Defaults to a generated one. |
| ...props | — | — | all | Everything else (name, value, onChange, aria-describedby, ...) lands on the <select>. |