Select
A select is the native <select> (Headless UI Select) with the field
styling of Input and a chevron drawn as a background image.
It takes plain <option> children and the browser's own picker, so it works
everywhere and needs no portal. For custom option rendering use
Listbox.
import Select from '@zuilib/components/select'
Variants
outline is the default field: --input border on --background. ghost
has no border until it is hovered or focused.
Sizes
sm, md and lg read --control-height-*, --control-padding-x-* and
the matching --text-* step. The chevron is --spacing * 6 wide and sits
half a control padding from the right edge; the text gets padding plus the
chevron on the right so it never runs under it.
States
state="error" paints the border and focus ring with --destructive and
also marks the control invalid; success uses --success. disabled
lowers the opacity and blocks the pointer.
In a FormItem
FormItem generates the id and wires Label, Description and Message to
the select. Its invalid becomes the select's default invalid, so one prop
on the item paints the border and sets aria-invalid.
Props
SelectProps extends the native <select> attributes (value,
defaultValue, onChange, name, disabled, multiple, …) minus size,
with:
| Prop | Type | Default | Description |
|---|---|---|---|
variant | 'outline' | 'ghost' | 'outline' | |
state | 'default' | 'error' | 'success' | 'default' | Validation state; error also marks the control invalid |
invalid | boolean | FormItem invalid | Sets aria-invalid / data-invalid and the error styles |
size | 'sm' | 'md' | 'lg' | 'md' | |
fullWidth | boolean | false | w-full on the select |
className | string | — | Merged last onto the native select |
Slots
| Slot | Element | Notes |
|---|---|---|
[data-slot="select"] | select | Root. Also data-state (default | error | success) and Headless UI's data-disabled, data-invalid, data-focus, data-hover |
Tokens
| Token | Used for |
|---|---|
--control-height-sm/md/lg, --control-padding-x-sm/md/lg | Box per size and chevron inset |
--spacing | Chevron width (* 6) |
--input, --background, --foreground | Outline border, surface, text |
--ring, --destructive, --success | Focus ring per state |
--radius-md | Corner radius |
--duration-fast | Colour transition |
Accessibility
- A real
<select>: keyboard (arrows, type-ahead,Space/Enterto open) and the platform picker come for free. - Label it with a
FormItemLabel, a<label htmlFor>oraria-label. invalid(orstate="error") setsaria-invalid; inside aFormItemtheMessageis reached througharia-describedby.disableduses the native attribute and inherits from an enclosingFieldset/FormItem.- The chevron is a background image, so it is never read or focusable.