Accessibility
Accessibility isn't a separate checklist — it's part of how every Senco component is built. All components target WCAG 2.1 Level AA as a minimum.
Target standard
WCAG 2.1 Level AA compliance for all components, patterns, and page templates. Level AAA where practical (e.g., enhanced contrast for financial data).
Color and contrast
| Requirement | Ratio | Applies to |
|---|---|---|
| Normal text | 4.5:1 | Body text, labels, descriptions |
| Large text (18px+ bold or 24px+) | 3:1 | Headings, large labels |
| UI components | 3:1 | Borders, icons, focus rings, form controls |
| Non-text contrast | 3:1 | Charts, graphs, status indicators |
- Never use color alone to convey meaning — always pair with text, icons, or patterns
- Status badges use color + dot indicator + text label
- Error states use red border + error icon + descriptive text
Contrast verification
All token pairings have been verified for WCAG AA compliance in both light and dark mode. See the full contrast tables and key decisions in Color > Accessibility.
Visible label above the input stays present when the user types.
Placeholder-only label disappears on focus, leaving no context.
All text and UI element pairings must meet minimum contrast ratios.
| Element | Minimum ratio | Standard |
|---|---|---|
| Normal text (<18px) | 4.5:1 | WCAG 1.4.3 AA |
| Large text (18px+ bold, 24px+) | 3:1 | WCAG 1.4.3 AA |
| UI components & icons | 3:1 | WCAG 1.4.11 |
| Focus indicators | 3:1 | WCAG 2.4.7 |
Keyboard navigation
All interactive components must be fully operable with keyboard only.
| Key | Action |
|---|---|
Tab | Move focus to next interactive element |
Shift+Tab | Move focus to previous element |
Enter / Space | Activate buttons, links, toggles |
Arrow keys | Navigate within menus, tabs, radio groups |
Escape | Close dialogs, tooltips, popovers, dropdowns |
Home / End | Jump to first/last item in a list |
Focus management
- Focus ring: 2px solid
--ds-primarywith 2px offset - Focus ring must meet 3:1 contrast against adjacent colors
- Focus order follows visual reading order (left-to-right, top-to-bottom)
- Never remove
:focus-visibleoutlines without providing an alternative - Dialogs trap focus and return it to the trigger on close
- Visible focus indicator on all interactive elements
- Focus ring meets 3:1 contrast against adjacent colors
- Custom focus styles consistent across the system
- Never remove outline without providing an alternative
3:1 contrast, 3px ring, visible on the focused element
Keyboard users cannot see where they are
- All interactive elements reachable via Tab
- Logical focus order matching visual order
- Escape key closes modals and overlays
- Arrow keys navigate within composite widgets
- Enter/Space activates buttons and controls
Tab index
Use tabIndex to control keyboard focus order.
| Value | Behavior | When to use |
|---|---|---|
tabIndex="0" | Follows natural DOM order | Custom interactive elements (div with onClick) |
tabIndex="-1" | Focusable via JS, skipped by Tab | Off-screen elements, programmatic focus (modals, error summaries) |
tabIndex="1+" | Forces priority order | Avoid — breaks natural flow, confuses users |
Semantic HTML
- Use native HTML elements whenever possible (
<button>,<input>,<nav>,<main>) - Avoid
<div>and<span>for interactive elements - Use heading hierarchy sequentially (h1 → h2 → h3, no skipping)
- Use landmark elements:
<header>,<nav>,<main>,<footer>,<aside> - Lists use
<ul>/<ol>, not styled divs
ARIA patterns
Use ARIA only when native HTML semantics are insufficient.
| Pattern | When to use |
|---|---|
aria-label | Icon-only buttons, unlabeled controls |
aria-describedby | Error messages, hint text, supplementary info |
aria-live | Dynamic content updates (toast, loading status) |
aria-current="page" | Active navigation item, breadcrumb current page |
aria-expanded | Accordion triggers, dropdown toggles |
aria-invalid="true" | Form inputs with validation errors |
role="alert" | Error summaries, critical notifications |
- Use semantic HTML first, ARIA second
- Apply ARIA roles and landmarks to define page regions
- Use aria-label, aria-describedby, and aria-live where needed
- Never use ARIA to override semantic meaning
Landmarks let assistive technology users jump between page regions.
Screen reader testing
Test all components with at least two screen readers:
| Platform | Screen reader | Browser |
|---|---|---|
| macOS | VoiceOver | Safari |
| Windows | NVDA | Firefox or Chrome |
| Mobile | TalkBack (Android) | Chrome |
| Mobile | VoiceOver (iOS) | Safari |
What to verify
- All interactive elements have accessible names
- Form errors are announced when they appear
- Page title updates on navigation
- Dynamic content changes are announced via
aria-live - Images have meaningful alt text (or
aria-hiddenif decorative)
- Meaningful alt text for images
- Hidden descriptive text for icon-only actions
- Live regions for dynamic content updates
- Form labels and error messages announced correctly
Alt text for images
alt="USDT wallet ending 9c1d, selected"alt="icon"alt="wallet"alt="South Korean flag — Min-ji Kim, sent $250 CAD"alt="flag"alt=""Skip to content
A skip link is a hidden anchor that becomes visible on keyboard focus. It lets users bypass repetitive navigation and jump straight to the main content area.
- The skip link must be the first focusable element on the page
- It is visually hidden by default and appears on
:focus - The target must be a landmark with an
id(e.g.,#ds-main-content) - Skip links are required on every page with persistent navigation
<body>
<a href="#main" class="ds-skip-link">
Skip to main content
</a>
<nav>...</nav>
<main id="main">...</main><body>
<nav>...</nav>
<a href="#main">
Skip to main content
</a>
<main id="main">...</main>Motion and animation
- Respect
prefers-reduced-motionmedia query - Disable non-essential animations when reduced motion is preferred
- Essential animations (loading spinners) remain but simplify
Touch targets
- Minimum touch target size: 48×48 CSS pixels (exceeds WCAG 2.5.5 AAA)
- Minimum spacing between targets: 8px
- The visual element can be smaller — the tappable hit area must be 48×48px
Checklist
Use this checklist for every new component or pattern:
- Color contrast passes 4.5:1 for text, 3:1 for UI
- Keyboard operable (Tab, Enter, Escape, Arrow keys)
- Focus indicator visible and meets contrast requirements
- Screen reader announces name, role, and state
- Error states use text + icon, not color alone
- Touch targets are 48×48px minimum
-
prefers-reduced-motionis respected - Semantic HTML used (no div buttons)
- ARIA attributes correct and minimal
- Tested with VoiceOver and NVDA