RFC-003: Canonical Select Component
Status: 🟡 Draft — Under review
Tier: 1 (Canonical)
Inherits From: — (root component)
Author: AI Agent
Date: 2026-07-02
1. COGNITIVE PURPOSE
Select exists to allow users to choose exactly one option from a predefined list. It reduces cognitive load by eliminating free-form input when the valid options are known in advance.
Design Goal: The user can see available options, make a selection, and confirm their choice without typing or guessing.
2. WHEN TO USE
- Choosing from 5–20 predefined options
- Selecting a single value (country, status, category)
- When options have clear labels
- When free-form input would cause errors
3. WHEN NOT TO USE
- Fewer than 4 options (use Radio Group or Segmented Control)
- More than 50 options (use Searchable Select or Autocomplete)
- Multiple selections (use Multi-Select or Checkbox Group)
- Boolean choice (use Switch or Checkbox)
- Free-form entry (use Input)
4. USER EXPECTATION
- Clicking the field reveals all options
- Selected option is clearly indicated
- Current selection is visible when closed
- Options are searchable if list is long
- Keyboard can navigate options
- Disabled options are visually distinct
5. INTERACTION CONTRACT
| Event |
Response |
| Click |
Open dropdown, show options |
| Click option |
Select option, close dropdown |
| Click outside |
Close dropdown, keep selection |
| Tab |
Move focus to next field, close dropdown |
| Arrow Down |
Open dropdown or move to next option |
| Arrow Up |
Move to previous option |
| Enter |
Select focused option, close dropdown |
| Escape |
Close dropdown, revert to previous selection |
| Type letter |
Jump to first option starting with that letter |
6. FAILURE BEHAVIOUR
| Scenario |
Response |
| No option selected |
Show placeholder, allow form submission if optional |
| Required but empty |
Show error on blur or submit |
| Option disabled |
Prevent selection, show disabled state |
| Options load asynchronously |
Show loading state, then populate |
| Options fail to load |
Show error, allow retry |
| User types non-matching letter |
No action, or show "no results" |
7. ACCESSIBILITY CONTRACT
- Label: Every Select MUST have associated
<label> or aria-label
- Role: MUST use
role="combobox" or native <select>
- Expanded: MUST communicate open/closed state with
aria-expanded
- Selected: MUST communicate selected option with
aria-selected
- Focus: Focus MUST move to dropdown when opened, return to trigger when closed
- Screen reader: MUST announce number of options, current selection, and position
- Keyboard: MUST support all interaction contract keyboard events
8. AI CONTRACT
| Scenario |
AI Choice |
| 5–20 predefined options, single choice |
Select |
| < 4 options, single choice |
Radio Group |
| > 50 options |
Searchable Select / Autocomplete |
| Multiple selections |
Multi-Select / Checkbox Group |
| Boolean toggle |
Switch / Checkbox |
| Free-form entry |
Input |
9. TOKEN DEPENDENCIES
| Token |
Semantic Alias |
Primitive |
Usage |
select-bg |
color.surface.default |
gray-0 |
Background |
select-border |
color.border.default |
gray-200 |
Default border |
select-border-focus |
color.border.focus |
blue-500 |
Focus border |
select-border-error |
color.border.error |
red-500 |
Error border |
select-text |
color.text.primary |
gray-900 |
Selected text |
select-placeholder |
color.text.muted |
gray-400 |
Placeholder text |
select-padding |
space-3 |
12px |
Internal padding |
select-radius |
radius-md |
8px |
Border radius |
select-height-sm |
space-8 |
32px |
Small height |
select-height-md |
space-10 |
40px |
Medium height |
select-height-lg |
space-12 |
48px |
Large height |
select-dropdown-bg |
color.surface.raised |
gray-50 |
Dropdown background |
select-dropdown-border |
color.border.default |
gray-200 |
Dropdown border |
select-dropdown-shadow |
shadow-md |
0 4px 6px rgba(0,0,0,0.07) |
Dropdown elevation |
select-option-hover |
color.surface.raised |
gray-50 |
Option hover background |
select-option-selected |
color.action.primary (at 10%) |
blue-50 |
Selected option background |
select-option-disabled |
color.surface.raised |
gray-50 |
Disabled option background |
select-error-bg |
color.status.danger (at 5%) |
red-50 |
Error background tint |
select-disabled-bg |
color.surface.raised |
gray-50 |
Disabled background |
select-disabled-text |
color.text.muted |
gray-400 |
Disabled text |
select-chevron |
color.text.muted |
gray-400 |
Chevron icon color |
10. LAYOUT
- Label: Above select, left-aligned,
text-sm, font-medium
- Trigger: Full width, padding
space-3, chevron icon right-aligned
- Dropdown: Full width of trigger, max-height 240px, scrollable
- Option: Padding
space-2 space-3, full width
- Helper/Error: Below select,
text-xs
- Gap:
space-1 between label and select, space-1 between select and helper
11. SIZES
| Size |
Height |
Font Size |
Padding |
Usage |
| Small |
32px |
14px |
space-2 |
Dense forms, tables |
| Medium |
40px |
16px |
space-3 |
Default, most forms |
| Large |
48px |
18px |
space-4 |
Mobile, touch-first |
12. VARIANTS
| Variant |
Visual |
Usage |
| Default |
Border, background |
Standard form select |
| Ghost |
No border, underline only |
Minimal UI, filters |
| Filled |
Solid background, no border |
High-contrast forms |
13. STATES
| State |
Visual |
Motion |
| Default |
select-border, select-bg |
— |
| Hover |
Border darkens |
duration-instant |
| Focus |
select-border-focus, focus ring |
duration-instant |
| Open |
Dropdown visible, chevron rotates |
duration-transition |
| Option hover |
select-option-hover |
duration-instant |
| Option selected |
select-option-selected |
duration-interaction |
| Option disabled |
select-option-disabled, muted text |
— |
| Disabled |
select-disabled-bg, select-disabled-text |
— |
| Error |
select-border-error, select-error-bg |
duration-interaction |
| Loading |
Spinner in trigger |
duration-attention |
14. KEYBOARD
| Key |
Action |
Tab |
Move focus to next field, close dropdown |
Shift+Tab |
Move focus to previous field |
Enter / Space |
Open dropdown or select focused option |
Arrow Down |
Open dropdown or move to next option |
Arrow Up |
Move to previous option |
Escape |
Close dropdown, revert selection |
Home |
Move to first option |
End |
Move to last option |
| Letter key |
Jump to first option starting with that letter |
15. TOUCH
- Touch target: Minimum 40px height (Medium size)
- Touch target for options: Minimum 44px height
- Active state: Brief background tint on option
- Scroll: Native scroll within dropdown
- No gesture support (no swipe to dismiss)
16. MOTION
| Transition |
Animation |
Duration |
Easing |
| Dropdown open |
Fade + slide down |
duration-transition |
ease-out |
| Dropdown close |
Fade + slide up |
duration-transition |
ease-in |
| Option hover |
Background color change |
duration-instant |
ease-out |
| Option select |
Background highlight |
duration-interaction |
ease-out |
| Chevron rotate |
Rotate 180° |
duration-transition |
ease-out |
| Error appear |
Border + background tint |
duration-interaction |
ease-out |
Reduced Motion: Dropdown appears/disappears instantly (duration-instant). No slide animation.
17. ANTI-PATTERNS
- ❌ Select with < 4 options: Use Radio Group instead
- ❌ Select with > 50 options: Use Searchable Select or Autocomplete
- ❌ No placeholder or label: User cannot infer purpose
- ❌ Disabled options without visual distinction: User thinks they can select them
- ❌ Dropdown wider than trigger: Breaks visual alignment
- ❌ Dropdown clipped by container: Use portal/overlay to escape overflow:hidden
- ❌ No keyboard navigation: Accessibility failure
- ❌ Changing options while open: Causes focus loss and confusion
18. RELATED COMPONENTS
- Input — Free-form text entry
- Radio Group — Few options, all visible
- Checkbox Group — Multiple selections
- Multi-Select — Multiple selections from dropdown
- Autocomplete — Searchable selection with free-form input
- Search — Input with suggestions
19. DDR REFERENCES
- DDR-001: Device Adaptive over Desktop First (affects sizing)
- DDR-002: Information-level typography (affects label and option text)
- DDR-003: Semantic color system (affects states)
- DDR-004: Motion System v1 intention-based tokens (affects dropdown animation)
20. ACCEPTANCE CRITERIA
ÄNDRINGSHISTORIA
| Version |
Datum |
Beskrivning |
| 1.0 |
2026-07-02 |
Initial RFC-003 following RFC-001 structure |
STATUS
DRAFT — Awaiting review