Skip to content

Select ​

Choose one or more options from a list that opens below the field.

Open in Storybook to try every prop.

When to use ​

Use Select forUse instead
One of about 4–30 known options: year group, school, subject2–3 options that should all be visible: radio buttons
Longer lists (about 10 or more): searchableLists too long to load, or searched on the server: a server-backed search
Several options from a list (multiple): subjects, recipientsSeveral from 2–6 options that should all be visible: checkboxes
Trees of options (children): Classes › Year 8 › 11Y/En2 › studentNavigating or running actions: a menu

Modes ​

Combine freely, e.g. searchable + multiple + nested.

ModePropThe field isWeb implementation
Single—A button showing the chosen optionReka UI Select
SearchablesearchableA text box that filters the listReka UI Combobox
MultiplemultipleChips for the chosen optionsEither
Nestedchildren on options(as above)Either

Anatomy ​

PartRequiredNotes
labelYesAbove the field. Also its accessible name.
helperNoBelow the label, or behind a ? icon.
fieldYesSame box as Input: shows the chosen option (or placeholder) and a chevron. When searchable it is a text box.
leadingNoThe chosen option's icon, or slot leading.
listYes (when open)Floating panel with the options, styled like Popover.
group headingNoSmall bold uppercase heading, with an optional icon; groups are separated by a line.
optionYesLabel (required), with an optional description under it and an optional icon before it, in any combination. A tick marks the chosen one.
back rowNested onlyFirst row inside a nested level: ‹ and the level's name (bold), then a divider. Goes up one level.
chosen chipsMultiple onlyA small Chip (20px, 4px corners, with the option's icon) per chosen option, in the field, wrapping onto more lines. When searchable each has × to remove it.
empty messageSearchable only"No matches" when a search finds nothing.
status messageNoError or success message under the field, as on Input.

Properties ​

PropertyTypeDefaultDescription
labelstring—Required.
modelValuestring | number, or an array of them when multiple (v-model)—The chosen value; undefined when nothing is chosen. With multiple, the chosen values in the order they were chosen ([] when none).
multiplebooleanfalseChoose any number of options.
options(string | { label, value?, description?, icon?, disabled?, children? })[][]Options in one list. A string is both label and value. Only the label and icon show in the field once chosen. value defaults to the label. An option with children opens them instead of being chosen.
groups{ label?, icon?, options }[][]Options under headings, shown after options.
searchablebooleanfalseType in the field to filter the options.
placeholderstringChoose… (Search… when searchable)Shown when nothing is chosen.
emptyTextstringNo matchesShown when a search finds nothing.
helper / helperPlacementstring / below | icon— / belowAs on Input.
errorText / status / statusTextAs on Input.
name / requiredstring / boolean—For native form submission and validation.
disabledbooleanfalse

Sizes ​

One size, matching Input and a md Button.

PartHeightPadding (y / x)GapIconText style
field38px (+24px per extra line of chips)8px / 12px8px16px (70% opacity)14px / 20px, regular
list panelup to the space available4px2px between options——
scrollbar————Thin system scrollbar when the list scrolls.
option32px with a label only; 48px with a one-line description (+16px per extra line)6px / 8px8px16px, level with the labellabel 14px / 20px (bold when chosen); description 12px / 16px, black 65%, wraps
chip (multiple)20px— / 6px4px between chips12px; × 16px12px / 16px, regular
label to field——6px——
group heading24px— / 8px6px14px, black 65%12px / 16px, bold, uppercase, black 65%
group divider1px2px above and below——black 15%; full width of the panel
PanelValue
Minimum widthThe field's width
Maximum width320px, or the field's width if wider; longer text wraps
Position5px below the field; above it if there's no room below
HeightUp to the space available on screen, then scrolls

Typography ​

Lato, sentence case, no letter spacing.

TextSize / line heightWeightColour
Label, chosen option, option label14px / 20px400 (option label 700 when chosen)black #050505
Placeholder14px / 20px400black 55%
Back row14px / 20px700black
Option description, search path12px / 16px400black 65%
Group heading12px / 16px700, uppercaseblack 65%
Chip12px / 16px400black
Helper, status message12px / 16px400black 65% / red / green

States ​

StateAppearanceNotes
EnabledWhite field, black 15% border. Placeholder in black 55%.
Focused2px focus ring #007FC9, 1px outside the border.
OpenChevron turns over (150ms); list fades in.
Option highlightedBlack 10% fill.Mouse hover or arrow keys.
Option chosenBold, with a tick at the right.
Option disabled40% opacity, can't be chosen.
Parent option› at the right instead of ✓.Nested.
ChipBlack 5% fill, black 15% border; × darkens to black 10% on hover.Multiple.
Error / successRed / green border and message, as on Input.
Disabled40% opacity, not-allowed cursor.

Behaviour ​

Keyboard ​

KeyClosedOpen
Enter / SpaceOpensChooses (Space: not when searchable)
↓ / ↑OpensMoves
Home / End—First / last option
LettersChooses the next option starting with them, without opening; searchable: opens and filtersHighlights the next option starting with them; searchable: filters
→—Opens the highlighted parent (searchable: only while nothing is typed)
←—Back one level (searchable: only while nothing is typed)
Backspace—Searchable multiple, empty search box: removes the last chip
Escape / Tab—Closes

Pointer and choosing ​

ActionSingleMultiple
Press the fieldOpens the listOpens the list
Press an optionChooses it, closes, focus back on the fieldTicks or unticks it; the list stays open
Press outsideClosesCloses
× on a chip—Removes it (searchable only; without search, untick in the list)
v-modelThe value, or undefinedAn array in the order chosen; [] when none

Searchable ​

ActionResult
TypeOpens the list; keeps options whose label or description contains the text, ignoring case and accents
Groups with no matchesHidden, with their divider
Nothing matches"No matches" (emptyText)
Press or focus the fieldSelects its text, so typing replaces it
Leave the fieldShows the chosen label again, or clears if nothing is chosen
Tick (multiple)The search clears, ready for the next

Nested ​

ActionResult
Choose a parent (›), or →Shows its children, with a back row (‹ and the level's name, bold) and a divider at the top
Choose the back row, or ←Goes up one level
After opening a levelHighlight on its first option
After going backHighlight on the option just left
ReopenSingle: starts at the chosen option's level. Multiple: starts at the top
SearchSearches every level; each match shows its path ("Classes › Year 8 › 11Y/En2"); the path is searched too
FieldShows only the chosen label, not its path

Shared options ​

The same option in several places (e.g. a student in two classes) must have the same value.

WhereResult
Chosen in one placeTicked everywhere it appears
Field (multiple)One chip
Chosen again anywhereUnticks it, so it can't be added twice
SearchOne row, listing every place: "Classes › Year 8 › 11Y/En2 · Classes › Year 8 › 8X/Ma1"

Motion ​

WhatDurationEasing
List fades in / out150msease-in-out
Chevron turns over150msease-in-out; none with reduced motion
Status message opens / closes150ms + 150ms text fadeease-out (as Input)

Content guidelines ​

TextGuidelineExample
LabelSays what is being chosen"Year group", not "Select year group"
OptionsSentence case, in a sensible order (natural, else alphabetical)Year 7, Year 8, Year 9
PlaceholderA prompt, never an option"Choose…", "Search…"

Accessibility ​

PartAnnounced as
Fieldcombobox named by <label for>: a button, or a text input with aria-autocomplete="list" when searchable
Helper / status messageLinked with aria-describedby; errors set aria-invalid
Listlistbox of options; groups named by their heading
Parent option"{label}, more options"
Back row"Back from {level}"
Chip ×"Remove {label}"
While openThe rest of the page is hidden from screen readers and can't be focused
ContrastRatio
Text on white19.5:1
Placeholder (black 55%) on whiteabout 4.5:1
Focus ring on white4.1:1 (minimum 3:1)

Platform adaptation ​

PlatformImplementationDifferences
Web / desktop (Vue)Select.vue (Reka UI Select; Combobox when searchable)—
iOS (SwiftUI)—Picker with .menu style inside a labelled row; searchable: a pushed list with .searchable.
Android (Compose)—ExposedDropdownMenuBox (read-only; editable when searchable).

Tokens used ​

TokenUsed for
color white, blackfield and list background, text
color black (15%)borders, group separators
color black (10%)highlighted option, chip × hover
color black (5%)chip fill
color focusfocus ring
color red / greenerror / success border and message

Do / Don't ​

DoDon't
Keep lists short enough to scan, make them searchable, or nest them (e.g. year › class › student).Use a select for 2 options (use radios).
Give options with icons a label too.Put actions ("Add new…") among the options.
Give every option in a list an icon, or none. Descriptions can vary per option.Mix options with and without icons: the labels won't line up, and indenting them makes them look nested.
Use the same value for the same thing in several places.Give each copy its own value: it will be treated as a different option.

Released under the PolyForm Noncommercial License 1.0.0.