Select
A native (<select>), hydration-free select. It renders correct,
functional markup with JavaScript turned off and emits native change
events — which is why it works in pure static SSG (renderToStaticMarkup,
zero application JS), where InputSelect
(based on react-select) does not.
The native <select> is encapsulated inside the component: you pass typed
options, never raw <option>/<select>.
When to use
| ✅ Use when… | 🚫 Avoid when… |
|---|---|
|
|
Example
<Select
name="theme"
aria-label="Theme"
defaultValue="light"
options={[
{ value: 'light', label: 'Light' },
{ value: 'dark', label: 'Dark' },
{ value: 'grayscale', label: 'Grayscale' },
]}
/>Sizes
<Select size="small" options={options} />
<Select size="medium" options={options} />
<Select size="large" options={options} />small is the smallest step. There is no micro size — in Apollion micro is
a fontSize token, not a control size.
Border radius
borderRadius accepts the theme's radius scale. straight keeps the corners
square; circular, fully rounded (pill).
<Select borderRadius="straight" options={options} />
<Select borderRadius="xs" options={options} />
<Select borderRadius="circular" options={options} />Accessibility & SSR
- Always provide an
aria-label(or an associated<label>), since the control does not render a visible label of its own. - Keyboard focus shows a visible
:focus-visibleoutline. - Native
optioncolors are forced (dark text on the lightest surface) so the system popup remains readable on dark surfaces. - No
useEffect, no hydration: the rendered markup is fully functional with JavaScript turned off.
Interactive Demo
loading
Properties
Prop | Type | Default | Description |
|---|---|---|---|
options * | SelectOption[] | — | Typed options rendered as native `<option>` elements. |
size | "small" | "medium" | "large" | medium | Control size token (height + horizontal padding). |
variant | "default" | "success" | "error" | default | Visual variant reflecting validation state, consistent with the other
form controls (`Input`, `InputSelect`). |
In addition to the props above, every component accepts the layout props (spacing, color, flex/grid, sizing, border) — not repeated here.
Theming (theme.component.select)
The size scale is a component token: theme.component.select.size.{small,medium,large}, each carrying height (px) and px (spacing alias). Override one field of one size without forking the component:
createTheme({
component: {
select: {
size: {
medium: { height: 44 },
},
},
},
});See also
- Storybook story: Components / Select
- Theme presets for accessibility: Accessibility Presets
- Select with search / multi / async:
InputSelect - Immediate-effect boolean:
Switch - Exclusive choice as a group:
Radio