Components · Form

Select

A select lets the user choose one option from a list. It looks and behaves like an input field, with a dropdown arrow. It opens the ECO Menu as its list.

Tokens, sizes, measurements, states and requirements. Values come from the live token package and from Figma: Base Input.

Design Tokens

Resolved from the live token package.

StatePartTokenValue

Hover is border-hover (#333333, the same value as border-dark). Active is read from the chosen option with :has(), so no script is needed.


Sizes

Breakpoint · sizeHeightPadding (left, right)ArrowLabelSelect text
Desktop · Large48px12px, 40px24pxlabel-md 16/16, 0.48pxbody-md 17/24, 0.32px
Desktop · Small40px8px, 40px24pxlabel-sm 14/14, 0.56pxbody-sm 14/20, 0.36px
Desktop · XSmall32px8px, 40px24pxlabel-sm 14/14, 0.56pxbody-sm 14/20, 0.36px
Mobile · Large40px8px, 40px24pxlabel-sm 12/12, 0.48pxbody-md 16/22, 0.32px
Mobile · Small32px8px, 40px24pxlabel-sm 12/12, 0.48pxbody-sm 14/20, 0.36px

Measurements

Dimensions

Padding of the select at each size. The shaded areas are the padding to the left and right (40px on the right leaves room for the arrow); the box is fixed in height. The numbers are read from the component.

Breakpoint
The select at true size (1:1). Change the Breakpoint to see the mobile values.
AttributeLargeSmallXSmall
Height, Desktop48px40px32px
Height, Mobile40px32pxNot available (use Small)
Padding left, Desktop12px8px8px
Padding left, Mobile8px8pxNot available
Padding right40px: room for the arrow
Arrow24px icon, 12px from the right edge, centered vertically
Border1px
CornersSquare

Spacing

The same padding and distances as spacing tokens.

PartValue
Label to boxspace-4
Box to messagespace-4
Padding left, Desktop Largespace-12
Padding left, otherwisespace-8
Padding right40px: literal, no token
Arrow from the right edgespace-12
Menu below the fieldspace-4
Focus ring2px line, 3px outside the box

States

The seven states from Figma, plus Open (the menu is open: black border and the arrow turned 180°). Hover, focus and open are forced on this page; in your code they come from :hover, keyboard focus and aria-expanded="true". The open list itself is shown on the Menu page.

Breakpoint
Size
StateNo valueValue chosen

Active means an option is chosen. Click a field to open its Menu. Active without a value is not defined: it shows a dash.


Typography

PartTypeSize / line heightLetter spacingWeight
Label, Desktop Largelabel-md16/160.48pxBold, uppercase
Label, Desktop Small, XSmalllabel-sm14/140.56pxBold, uppercase
Label, Mobilelabel-sm12/120.48pxBold, uppercase
Select text, Largebody-md16/22 mobile, 17/24 from 769px0.32pxRegular
Select text, Small, XSmallbody-sm14/200.36pxRegular
Messagebody-sm14/200.36pxRegular

Breuer Condensed with ss02 and ss03 (the select text and the message also ss06).


Structure

Elements

ElementClassNotes
Fieldform-fieldLabel, wrapper and message in a column, 4px apart.
Labelform-label, form-label--smUppercase. --sm for Small and XSmall.
Wrapperinput-wrapCarries the focus ring, the arrow and the open menu.
Selectform-select, --sm, --xs, --error, --successThe native select, appearance: none.
Arrowform-select-arrowMaterial Symbols arrow_drop_down, 24px.
Messageform-helper, --error, --success, --disabledOptional icon (form-helper-icon).
Menumenu, menu--smAdded under the wrapper by select-menu.js while open.

Types

There is one type. The Menu size follows the field: Large opens a Large menu, Small and XSmall open a Small menu.

Width

The field fills its container. The menu is as wide as the field.


Motion

PropertyDurationEasing
border-color of the selectduration-fast-3ease-standard
opacity of the focus ringduration-fast-3ease-standard
Arrow rotation (180° when the menu is open)duration-fast-3ease-standard
Menu opens: fade in and move 8px away from the fieldduration-medium-1ease-decelerate-generic
Menu closes: fade out and move 8px backduration-fast-2ease-accelerate-generic

The menu opens downwards, or upwards when it has flipped; the 8px move follows that direction. Under prefers-reduced-motion it opens and closes instantly.


Behavior

InputResult
ClickOpens the Menu under the field (no ring on mouse) and the arrow turns 180° clockwise; it turns back when the menu closes. Click a row to choose; click outside to close.
TabThe blue ring shows on keyboard focus only (body.keyboard-nav).
Enter, Space, Arrow keysOpen the Menu on the chosen row. Up and Down, Home and End move; Enter or Space choose; Escape closes and returns focus to the field; Tab closes.
PlaceholderA first option with value="" (disabled, hidden) shows the placeholder in text-tertiary.
Menu positionUnder the field. It flips upwards when it does not fit below and there is more room above; otherwise its height is capped and it scrolls.
DisabledNot focusable. Grey fill, light border, text-disabled text and arrow.

Accessibility Requirements

TopicRequirement
LabelAlways a label with for and id. A placeholder is never the label.
ErrorSet aria-invalid="true" and point aria-describedby at the message.
ListThe Menu is a listbox of option rows, with aria-selected, named by the label. The select gets aria-expanded while it is open.
FocusA 2px ring on keyboard focus (border-focus), not on mouse click (WCAG 2.4.7, 1.4.11). Escape returns focus to the field.
ColorError and success are not shown by color alone: the message says it, and the error message has an icon.
DisabledNot focusable. Disabled tokens are exempt from contrast requirements.