Accessibility
Generated from DESIGN_SYSTEM.md
Rules
WCAG 2.2 Level AA is the mandatory baseline on every platform โ web, iOS, Android, and the browser extension. We additionally claim a small AAA "stretch" set we already meet; we do not pursue full AAA. This section governs: where an older rule in this doc conflicts (notably any "40โ50% opacity" text tier โ in Philosophy, Typography, Data Source Attribution, etc.), the contrast floors here win.
Level commitment
- AA 2.2 โ required. Aligns with KR (KWCAG 2.2 / ์ฅ์ฐจ๋ฒ), US (Section 508 / ADA โ WCAG AA), and EU (EN 301 549 โ 2.1 AA).
- AAA stretch โ only these (already met or near-free):
2.5.5Target Size 44px (we already mandate 44/48);2.3.3animation-from-interaction (reduced-motion respected);1.4.67:1 contrast aspired for primary body text. All other AAA is out of scope.
Perceivable
Contrast floors โ these replace the opacity tiers. Text tone is limited to contrast-validated tokens; never lower text below its floor with opacity. The 40โ50% muted/caption tier is removed โ captions differ by size/weight.
| What | AA floor | Source |
|---|---|---|
| Body / caption text (< 18.66px bold, < 24px) | 4.5:1 | 1.4.3 โ text-primary (aim 7:1), text-secondary |
| Large text (โฅ 18.66px bold, โฅ 24px) | 3:1 | 1.4.3 |
| UI components, meaningful icons, sole control/state boundaries, focus ring, graphs that convey meaning | 3:1 | 1.4.11 (non-text) |
Purely decorative (a border-subtle separator that isn't the only signal; disabled controls) | exempt | 1.4.3 / 1.4.11 |
- Color is never the only signal (1.4.1). Active/status/error states pair color with icon, text, shape, or weight โ never color alone.
- Meaningful images carry alt text / labels (1.1.1).
Operable
- Full keyboard (2.1.1 / 2.1.2). Every action reachable and operable by keyboard, no traps. (The "every navigation is a real anchor" rule already serves this on web.)
- Focus visible + unobscured (2.4.7 / 2.4.11 / 2.4.13). Every interactive element shows a focus indicator โฅ 3:1 vs. adjacent colors; never
outline: nonewithout a stronger replacement. Sticky chrome (top glass bar, FAB, bottom nav) must not cover the focused element โ use scroll-padding / offsets so focus stays on screen. - Target size 44pt+ (exceeds AA's 24px
2.5.8; meets AAA2.5.5). - Dragging alternative (2.5.7). Any reorder/drag offers a non-drag path (menu / buttons).
- Reduced motion โ every non-essential animation respects
prefers-reduced-motion/ Reduce Motion.
Understandable
- Labels above fields, never placeholder-only (3.3.2); errors inline + specific, not page-level only (3.3.1 / 3.3.3).
- Accessible Authentication (3.3.8). Login / PIN / OTP fields allow paste + password managers; no transcription, memorization, or puzzle step. Applies to the PIN gate and the extension OAuth sign-in.
- Predictable navigation + consistent help location (3.2.3 / 3.2.6); no redundant re-entry of known info (3.3.7).
Robust
- Native components / valid semantic markup; name-role-value exposed (4.1.2). Web:
aria-*+ roles, status linearia-live. iOS:accessibilityLabel/Traits + Dynamic Type. Android:contentDescription+ TalkBack +spunits. - Reflow at 320px (1.4.10 โ already mobile-first) and text resize to 200% (1.4.4 โ
rem/ Dynamic Type /sp; never fixed-px text).
Per-platform a11y API
| Concern | Web | iOS | Android |
|---|---|---|---|
| Label | aria-label / <label> | accessibilityLabel | contentDescription |
| Live region | aria-live | accessibility announcement | liveRegion |
| Resize / scale | rem + browser zoom | Dynamic Type | sp units |
| Focus | :focus-visible ring | accessibility element + traits | default focus + traversal |
| Reduced motion | prefers-reduced-motion | isReduceMotionEnabled | animator duration scale |
Live specimens
Every screen has one clear focal point
label-primary ยท Floor 4.5:1, aim 7:1
Every screen has one clear focal point
label-secondary ยท Floor 4.5:1
btn-icon ยท 44pxw-11 h-11 ยท 44px