Select
One value out of a list: a list over its trigger with a mouse, the platform's own picker on phones and tablets.
One skill, every component.
Install
The select is part of the boilerplate skill, with every other component on this site. Install it in your project's folder; it works in Claude Code, Codex, Cursor and other agents. Already done? Skip ahead. More in the Introduction.
npx skills add frontendsupply/skills --skill boilerplateAsk
Then ask for it in your own words, or run the command. The skill reads your project's style first and writes the component in it. If the project has no select yet:
/boilerplate add selectIf it already has one, the skill rebuilds it on this pattern and keeps its look, its names and every place that uses it working:
/boilerplate refactor selectEither way it ends by proving that only the look changed: a script checks every behavior class and slot is still there.
The choice lands on the value.
Over the trigger
The list opens over its trigger, with the chosen item exactly where the value was, so the eye doesn't move: the rows share the trigger's height and its inset, their text starts where the value does, after an icon too, and the check sits where the chevron was. A list longer than the room it has scrolls, with arrows at its ends that scroll while the pointer rests on them. Near the top or bottom of the screen, or opened by touch, it opens below the trigger instead.
Labels, rules, items not offered.
Sections
Items come in groups, each under a label in small capitals, with a rule between them if you like. An item can be shown but not offered: it dims and can't be chosen.
Legal and Tabloid are out of stock.
Several at once
A select can hold more than one value. Then the list opens below the trigger rather than over it, so the choices so far stay in view, and it stays open while you pick. The trigger lists them, cut short with an ellipsis when they don't fit.
Pick several; the list stays open.
Beside an input.
In a form
A select is drawn like the Input's field: one height, one inset, the same placeholder, focus ring, error and disabled look, so a form of both reads as one. In a field it takes the same label, description and error, and is checked and sent with the form.
Nothing moves.
One width
In a form a select fills its field. Set narrower, in a toolbar, it's as wide as its longest item, as a native select is, so choosing a shorter or a longer one never pushes what's beside it.
The platform's picker.
Phones and tablets
On a phone or a tablet the select hands over to the device's own picker: the wheel or the sheet on an iPhone, a popover on an iPad, a dialog on Android, with sections, items not offered and several at once all carried over. Under the trigger sits a real, invisible select, so a tap anywhere on it opens the picker and autofill can fill it. The value, the name it's sent under and the field around it are the same in both, so the code using it never asks which one it got.
The device decides, never the width of the window: a narrow window on a laptop keeps the list, and an iPad gets the picker even though its browser says it's a Mac. Pages rendered on a server start with the list's trigger and switch on arrival; the two look alike, so nothing flickers. A list with things an option can't hold, a picture or a second line, can keep the list everywhere.
Disabled and read-only
A disabled select dims and isn't sent with its form. A read-only one opens, so you can see the choices, but keeps its value.
Read-only: open it to see the sizes; the choice stays.
What lines up.
Alignment
A select and its list at their real size, with the lines their parts share. Hover a line to see what sits on it: the section label in line with the trigger's icon; every item starting where the value does; the check on the chevron's axis; trigger and list one width, every row as tall as the trigger; and every part on its row's center line. The dashed lines are the trigger's and the list's edges. A part a pixel off would show as a line of its own.