Select
Select is a styled native <select>, not an APG combobox. Use it for a known list that stays manageable
without filtering, and let the browser own its picker, keyboard behavior and platform conventions.
Examples
Label, hint and native options
Use a disabled empty option when a choice is required. The label names the decision after the picker closes; a placeholder-like first option cannot replace it.
Used to tailor your workspace.
Sizes and error
Select shares the form-field height tokens. error replaces hint and adds aria-invalid,
keeping one message connected to the control instead of stacking feedback.
Choose the billing country.
When to use
Use Select for one choice from a short, stable list where the native picker is enough.
Reach for something else when:
- The list needs filtering or rich option detail — use Combobox, which provides a searchable listbox.
- All few choices should remain visible and one must be selected — use Radio so people can compare them without opening a picker.
- Several choices can be true — use Checkbox rather than overloading a single-select control.
Accessibility
- Renders a native
<select>with native<option>or<optgroup>children; browser keyboard and picker behavior apply. - A supplied
labeluseshtmlForwith a generated or consumerid. Without a label, provide an accessible name. hintorerroris connected witharia-describedby;errortakes precedence and setsaria-invalid.- Focus uses
--shadow-focus. Do not document custom listbox keystrokes here: this is not a custom combobox.
Props
| Name | Type | Required | Description |
|---|---|---|---|
label | string | — | Label rendered above the select and associated through `htmlFor`. |
hint | string | — | Helper text rendered below the select. Replaced by `error` when provided. |
error | string | — | Error message that enables error styling and `aria-invalid`. |
size | 'sm' | 'md' | 'lg' | — | Control height. Default `"md"`. |
children | ReactNode | Required | Native `<option>` or `<optgroup>` children. |
Plain HTML
Place the native select in its wrapper so the CSS arrow can sit over the control without receiving clicks:
<div class="lyra-field">
<label class="lyra-label" for="team-size">Team size</label>
<span class="lyra-select-wrap">
<select class="lyra-input" id="team-size">
<option value="">Choose a range</option>
<option value="1-10">1–10 people</option>
<option value="11-50">11–50 people</option>
</select>
</span>
<span class="lyra-hint">Used to tailor your workspace.</span>
</div>
<div class="lyra-field">
<label class="lyra-label" for="country">Billing country</label>
<span class="lyra-select-wrap">
<select class="lyra-input lyra-input--error" id="country" aria-invalid="true"></select>
</span>
<span class="lyra-hint lyra-hint--error">Choose the billing country.</span>
</div>