Inputs
Select
A styled wrapper around a native select, accessible and zero-JS. Compose it inside a Field for its label, description and error.
Import
import { Field, Select } from "@loamui/core";Usage
Every example has a CSStab. That’s the real, complete stylesheet for the component: plain, static CSS, with nothing running in the browser.
Basic usage
Wrap the control in Field.Root and add a Field.Label: the select reads its id from the field, so the label is wired without any props.
With placeholder
Pass a placeholder to render an empty prompt option first.
Groups and disabled options
Options pass straight to the native select, so optgroup and disabled work exactly as the platform defines them.
With a description
Field.Description links to the select via aria-describedby, the same wiring every control gets inside a Field.
Where you are resident for tax.
Error state
A Field.Error after the control marks the field invalid and is announced: the message's presence is the state.
Error: Select a country
Guidance
When to use it
- For choosing one option from a longer list (roughly 5+) where showing them all would take too much space.
- When the options are familiar and the user doesn't need to compare them side by side.
When not to
- For a small set of options the user should see at once: use Radio, which shows every choice up front.
- For yes/no or on/off: use Checkbox or Switch.
- For free-form input: use Input.
Accessibility
- Wraps a native <select>, so keyboard interaction, typeahead and the mobile picker come from the platform.
- Inside a Field.Root it self-wires: the label, description and error are linked via id / aria-describedby / aria-invalid, with the error announced as role="alert". See the Field page.
- A placeholder renders as a disabled first option so it is never a selectable value.
How it works
Start without a value
Pass placeholder to render a disabled, empty first option, so the field starts unanswered and required validation catches an untouched select. Without it the first real option is pre-selected, and users who skip the field silently submit an answer they never chose.
Order the options
List options alphabetically so users can predict where an answer sits in a long menu, the reason to use a Select at all. Depart only for an order that is genuinely more useful in the domain, like months in calendar order or years newest-first.
A select conceals its options
Until opened, the menu shows one value and hides every alternative, so users can't survey or compare the choices. The cost shows up in usability testing: people try to type into the closed control, mistake the focused option for a selected one, and struggle to operate the menu zoomed in. That is the cost that makes RadioGroup the better control for small sets. Reserve Select for long lists of familiar answers users recognise rather than weigh up.
Error messages
Say what happened and how to fix it, in the words of the question itself. See the writing guidance on the Field page.
| Situation | Message |
|---|---|
| Nothing is selected | Select [whatever the label asks for] |
Props
| Prop | Type | Default | Description |
|---|---|---|---|
placeholder | string | — | Non-selectable prompt shown as the first, empty option. |
children | ReactNode | — | Native <option> / <optgroup> elements, passed straight through. |
wrapperClassName | string | — | Class for the bordered field wrapper; className goes to the control itself. |
...others | SelectHTMLAttributes | — | All native <select> props are forwarded, except size (sizing is contextual). |