abaabil

Select

4th lightest of the eight, by js weight

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 only
import Select from 'abaabil/select/styled'  // + CSS
import Select from 'abaabil/select/a11y'    // + label/description/error wiring

Why 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> via htmlFor/id.
  • Joins whichever of description and error are present into one aria-describedby.
  • Sets aria-invalid when error is present.
  • Warns in development if label is omitted, since the platform gives a bare <select> no accessible name on its own.

Props

PropTypeDefaultTierDescription
optionsArray<{value, label}>allRendered as <option> elements. Omit and pass children directly for <optgroup> or custom option markup.
childrenReactNodeallUsed only when options is not given.
classNamestringallMerged with the base class.
labelstringa11yAccessible name, rendered as a real <label>.
descriptionstringa11yRendered and wired into aria-describedby.
errorstringa11yRendered, sets aria-invalid, joined into aria-describedby alongside the description.
idstringa11yExplicit id for the select. Defaults to a generated one.
...propsallEverything else (name, value, onChange, aria-describedby, ...) lands on the <select>.