Select
Picks one value from a list that opens over the trigger, the chosen item in place.
Delivered on Thursdays.
Installation
npx @yolkui/cli add selectUsage
Pass the options to Select as items ({ label, value }), so the trigger shows the chosen item's label; render each one as a SelectItem. The items also set the trigger's width: as wide as the longest label, as a native select is, so it never changes width with the choice; className="w-full" fills a form column. With a mouse the list opens over the trigger, the chosen item on the trigger's text, so the pointer is already on it. With the keyboard, on touch, or when there is no room, it opens below. alignItemWithTrigger={false} on SelectContent always opens it below.
- The trigger is Native Select's: the same surfaces, sizes and placeholder colour, so the two match in a form.
- For plain text options in a form that must work before JavaScript loads, or a list of hundreds, Native Select is lighter and uses the system's own list on phones.
Variants
soft, the default, is Input's surface, for forms. variant="outline" and variant="secondary" are the outline and secondary Buttons' surfaces, for a select on its own: a sort, a filter, a page size.
Sizes
Button's and Input's four heights, 28 · 32 · 36 · 40, and shape="pill". The size goes on SelectTrigger, and the list follows it: each item is 4px shorter than the trigger, its text where the trigger's is.
Groups and placeholder
SelectGroup with a SelectLabel heads a group of items; SelectSeparator draws a line between groups. A disabled item fades and is skipped by the arrow keys. Without a value, SelectValue shows its placeholder in the muted colour.
Long lists
A list taller than the screen scrolls. With a mouse, an arrow appears at each end that has more items, and hovering it scrolls the list; on touch it scrolls by hand. Typing the first letters of an item jumps to it.
Several values
With multiple, a click checks or unchecks an item and the list stays open; the form sends every value chosen. The trigger shows the first choice and how many more, "JavaScript (+1 more)", so it keeps one line and one width. formatMore translates the count; children, a function of the value, draws your own.
Pick any you work in.
In a group
In a ButtonGroup a soft select joins its neighbours like a field: square corners where they meet and one line at the seam. Give the group a width; the Input beside it takes the rest.
Invalid
In an invalid Field the edge and the focus outline turn red, and FieldError says why, with an icon and words.
Disabled
A disabled select fades, cannot be opened and is left out of the form. It stays focusable and keeps pointer events, so a Tooltip around the trigger can say why, on hover and on keyboard focus; screen readers announce it as dimmed. If the reason matters to everyone, phones included, write it in a FieldDescription (Region); a Tooltip never shows on a tap (Plan).
The region is set when the project is created.
Accessibility
The trigger is a combobox and the list a listbox. Space, Enter or the arrow keys open it on the chosen item; the arrows move, Home and End go to the ends, typing jumps to an item, Enter picks it and Escape closes the list and returns focus to the trigger. Screen readers hear the label, the chosen value and "pop-up button" or "combo box".
- Give it a label: a FieldLabel in a Field, or aria-label on SelectTrigger when it stands alone.
- Keep it out of a Toolbar: a toolbar moves focus with the arrow keys, which open a select and move inside its list.
- The selected item is marked with a check and a heavier weight, never colour alone.