Components · Inputs
Select
BetaPicks one option from a short list, such as a program goal.
- Source
components/ui/select.tsx - shadcn/ui Select
- Figma: not linked yet (Q13)
When to use
- To pick one option from a list of about 5 to 15: a program goal, a currency, a check-in frequency.
When not to use
- 2 to 4 options that should all be visible: use a Radio group.
- Long or searchable lists such as the exercise library: use a combobox.
- To choose several options: use checkboxes.
- For actions ("Duplicate", "Archive"): use a dropdown menu.
Anatomy
- 1. Label
- 2. Trigger: shows the current value and a chevron
- 3. Listbox (opens from the trigger; try it): options, optional group labels, a check on the selected option
Variants
One style. Group long lists with SelectGroup and SelectLabel, as in the example above, and disable options that exist but can't be chosen yet.
States
Choose the currency for this package.
| State | What changes | Token |
|---|---|---|
| Focus-visible | Ring around the trigger | ring-ring/50 |
| Open | Listbox in popover with shadow-md, on the dropdown layer | bg-popover, z-(--z-dropdown) |
| Highlighted option | Accent fill | bg-accent, text-accent-foreground |
| Disabled | Half opacity | opacity-(--opacity-disabled) |
| Invalid | Red border, error text | border-destructive, text-destructive-text |
Usage guidelines
- Order options in a way coaches expect: by frequency, then alphabetically. Don't sort numbers as text.
- Use a placeholder only when no default makes sense, and phrase it as an instruction: "Choose a goal".
- Don't use a select for "Yes / No": use a switch or checkbox.
Content guidelines
- Options are short nouns, sentence case, no ending punctuation.
- Keep option text unique within the list, so type-ahead works.
Accessibility
| Key | Does |
|---|---|
| Enter, Space, Arrow down | Opens the list |
| Arrow up / down | Moves through options |
| Type a letter | Jumps to the next option starting with it |
| Enter | Selects and closes |
| Escape | Closes without changing the value |
- The trigger is a
comboboxlinked to its label; the list is alistbox. A screen reader announces "Program goal, combobox, Choose a goal". - Focus returns to the trigger on close.
RTL
- The chevron sits at the end and the check mark at the end of each option, so both move to the left.
- The list aligns to the trigger's start edge.
Tokens used
Read from components/ui/select.tsx at build time, so this list changes when the component does. Opacity modifiers such as /90 are shadcn hover and focus tints on top of the token.
| Token | Utilities | SuperCoach | Coach |
|---|---|---|---|
| --accent | bg-accent | brand-50 | orange-50 |
| --accent-foreground | text-accent-foreground | brand-700 | orange-700 |
| --border | bg-border | neutral-200 | neutral-200 |
| --destructive | border-destructive ring-destructive/20 | red-600 | red-600 |
| --input | border-input | neutral-200 | neutral-200 |
| --muted-foreground | text-muted-foreground | neutral-600 | neutral-600 |
| --popover | bg-popover | white | white |
| --popover-foreground | text-popover-foreground | neutral-950 | neutral-950 |
| --ring | border-ring ring-ring/50 | brand-600 | orange-500 |
- Layer
z-(--z-dropdown) - Opacity
opacity-(--opacity-disabled) - Radius
rounded-md - Radius
rounded-sm - Shadow
shadow-md - Shadow
shadow-xs - Type
text-sm - Type
text-xs
Props
<Select>
Also takes every prop of Radix Select.Root
No props of its own.
<SelectGroup>
Also takes every prop of Radix Select.Group
No props of its own.
<SelectTrigger>
Also takes every prop of Radix Select.Trigger
| Prop | Type | Default |
|---|---|---|
| size? | "sm" | "default" | "default" |
<SelectContent>
Also takes every prop of Radix Select.Content
No props of its own.
<SelectLabel>
Also takes every prop of Radix Select.Label
No props of its own.
<SelectItem>
Also takes every prop of Radix Select.Item
No props of its own.
Replaces in coach-admin
From the read-only audit of coach-admin: 97 style values, 147 uses.
coach-admin mixes its own select, a dropdown list and antd's Select; all three become this component.
Classes and selectors
.select__options5.select__option-icon3.ant-select.ant-select-focused .ant-select-selector2.select__option-label1.ant-select, .ant-select-dropdown1.ant-select-selector1.ant-select:not(.ant-select-customize-input) .ant-select-sel1.ant-select-dropdown1.select__wrapper1
Files
src/reusableComponents/formComponents/select/select.scss93src/reusableComponents/formComponents/dropdown-list/dropdown-list.scss38src/reusableComponents/formComponents/dropdown-list/DropdownList.tsx2
The inventory lists the first 12 locations of each value, so file counts are a lower bound.
SCSS variables in these styles
$primary-color→--primary