Select

Picks one option from a list that pops up.

Examples

Pay from

In a form

Sizes

  • sm

  • mddefault

  • lg

States

  • rest

  • placeholder

  • hover

  • focus-visible

  • open

  • invalid

  • disabled

Usage

When to use it
Use
One of 6 to 20 options: an account, a currency, a country.
Use
A form where a list of radios would take too much room.
Not for
Two to five options fit in a row. Use Segmented.
Not for
The options are a short list of radios. Use Radio.
Not for
More than about 20 options, or the person knows the name. Use Combobox.
Not for
The options are commands, not values. Use Dropdown menu.

Rules

9 rules
Must
Pass items to the root so the trigger shows the label before the popup opens. Because without items the trigger shows the raw value, such as savings, until the first open.
Must
Use placeholder on the trigger; never an item called "Select...". Because an empty item can be picked, checked and submitted as a real answer.
Should
Show five or fewer options as Radio or Segmented when there is room.
Never
Use a native select; this Select matches the popup, check and focus. Because the native picker is drawn by the OS, with no Lime panel, check mark or accent edge.
Must
Pass aria-label to the trigger when there is no visible label. Because a screen reader reads the chosen account with nothing saying what it pays from.
Must
Wrap the select in Field with a FieldLabel, and put errors in FieldError. Because Field ties the label and the error to the trigger, so both are read with it.
Should
Write short sentence-case noun labels with the distinguishing word first.
Never
Lift the popup height cap; lists scroll inside --popup-max. Because a long account list runs past the screen edge instead of scrolling inside the panel.
Should
Use size="lg" on the trigger in a phone form; items are 36px.

Accessibility

4 checks
The trigger is role combobox with aria-expanded; the popup is a listbox of options.
Enter, Space or Arrow Down opens; arrows, Home, End and type-ahead move; Enter chooses; Escape closes.
Focus returns to the trigger on close; Escape in a dialog closes the popup first.
A highlighted item has only a fill, so forced colors paints it with Highlight.

Edge cases

6 edge cases
Long label
Trigger and items truncate with an ellipsis; keep labels short or widen the trigger.
Narrow container
The trigger has a 160px floor; set w-full min-w-0 to follow the container.
Right to left
Caret, padding and check mirror.
No items
The popup opens empty; render text instead of an empty Select.
List loads late
There is no loading row; render the select when items arrive.
Inside a dialog
The popup portals into the Lime scope and keeps the tokens.

API

5 props
items
Array<{value, label}> | Record
value, defaultValue, onValueChange
Value
SelectTrigger size
'sm' | 'md' | 'lg' default 'md'
SelectTrigger placeholder
string
SelectItem value
Value default required

Tokens

20 tokens
--field
#f6f5f2
--line-strong
#cfcdc6
--fg
#0f0f0d
--fg-3
#6b6a63
--control
#85827a
--accent-line
#7c8700
--ring
var(--accent-line)
--line-focus
2px
--danger
#d93636
--surface-2
#efeeea
--fg-disabled
#a6a49b
--raised
#ffffff
--shadow-menu
0 8px 24px -6px rgb(var(--shadow-ink) / 0.16), 0 2px 6px rgb(var(--shadow-ink) / 0.06)
--radius-panel
16px
--radius-md
10px
--popup-max
320px
--dur-base
200ms
--dur-fast
140ms
--ease-out
cubic-bezier(0.16, 1, 0.3, 1)
--scale-enter
0.97

Install

For your coding agent

GitHub

Please star me pookie

141

A new design system every week

Leave your email before you copy the prompt.