Interaction — Selection
interaction specs/interaction/selection.kmd
How users mark/unmark items as selected — single-select, multi-select, range-select, and the visual + accessibility contract for each. Material parity (`/foundations/interaction/selection`). Used by lists, tables, file pickers, chips, and any UI where selection is a primary action.
When this spec applies
Primary triggers
- Implement selection in a list or table
All triggers
- Build a UI where users select one or more items
- Decide between checkbox, radio, chip, or row-tap selection
- Add bulk actions to a list/table
Specification body
Spec — Interaction: Selection
Facet Visual do Koder Design. Material parity: https://m3.material.io/foundations/interaction/selection.
3 selection patterns
| Pattern | Cardinality | Affordance |
|---|---|---|
| Single | 1 of N | Radio button OR row-tap (mutually exclusive) |
| Multiple | 0..N | Checkbox OR chip (toggle) OR row-tap+modifier |
| Range | contiguous span | Click + Shift+Click; or drag |
R1 — Affordance per cardinality
Single-select
- Radio buttons when N ≤ 5 and all options must be visible
- Dropdown / select when N ≥ 6 OR options take vertical room
- Row-tap (no visual control) when the selection IS the navigation (list-detail layout — tapping a row reveals its detail)
Multi-select
- Checkbox when each item is identified by a row in a list
- Chip (filter style) when options are short labels, often spatial (e.g., date ranges, tags)
- Row-tap with selection mode — long-press enters selection mode; subsequent taps add/remove. Mobile pattern from Gmail/Files.
Range-select
- Click first item, Shift+Click last — desktop pattern
- Drag across items — touch and desktop both
- Date range picker — specialized component for time
- Always combinable with multi-select (Ctrl+Click toggles individual)
R2 — Visual state per selected item
| State | Marker |
|---|---|
| Unselected | Default surface; no visual marker |
| Selected | Accent-tinted background (low opacity) + checkmark/radio dot + bolder border |
| Hover (selectable, unselected) | Surface-variant background; cursor pointer/finger |
| Hover (selected) | Selected style + slightly elevated tint |
| Focused (keyboard) | 2px focus ring per states.kmd |
| Disabled | Reduced opacity; no hover/focus response |
Selected background opacity recipe:
color-mix(in srgb, var(--accent) 12%, transparent) (or theme-equivalent)
R3 — Accessibility
- Selection controls (radio/checkbox) must have:
role="radio"/role="checkbox"if not native<input>(prefer native)aria-checked("true"/"false"/"mixed")aria-labelor visible label
- Row-tap selection must announce state change to screen readers via live region: "Selected. 3 of 12 items."
- Keyboard: Space toggles, arrows navigate (in list/grid), Shift+arrow extends range, Ctrl+A selects all (if applicable)
R4 — Bulk action affordance
When multi-select is active:
- A bulk action bar appears (top of list or floating) with:
- Count: "3 selected"
- Primary actions: Delete, Archive, Tag (per surface)
- Cancel / Deselect all
- Bar uses selected color scheme — accent-tinted, not error-tinted, even for destructive actions (preserve destructive semantics inside per-button styling)
- Bar is reachable by keyboard (Tab from any selected row)
R5 — Persistence
Selection state is ephemeral by default — refreshing the page clears.
Exception: when the user navigates within a single workflow (e.g., list → detail → back), restore the previously selected item. Use URL fragment or session storage; clear on workflow exit.
R6 — Edge cases
- Empty list with selection mode — exit selection mode automatically
- All items selected — show "Deselect all" instead of "Select all"
- Mixed state (some descendants selected in a tree) — checkbox shows
aria-checked="mixed"and indeterminate visual - Selection during async load — preserve user intent; if items rearrange, keep selection by ID not by index
Cross-link
interaction/states.kmd— focus/hover/pressed/disabled detailsfoundations/elements.kmd— selection is a control affordancethemes/color-schemes.kmd— accent-tinted background token
References
specs/foundations/elements.kmdspecs/interaction/states.kmdspecs/themes/color-schemes.kmd