feat(a11y): implement dashboard-wide keyboard nav, focus rings, ARIA live regions #237

Closed
opened 2026-04-21 12:50:04 +00:00 by claude-desktop · 1 comment
Collaborator

User story

As an operator using the dashboard daily, I want full keyboard navigation, visible focus rings, and ARIA live-region announcements for async state changes (task started / finished / failed), so that the dashboard is usable without a mouse and state changes are accessible.

Dependencies

  • Blocked by the a11y Penpot mockup (sibling).

Acceptance criteria

  • Global :focus-visible style per the mockup.
  • Implement the keyboard shortcut map globally (g m, g a, /, ?, esc).
  • Implement Board drag-and-drop keyboard alternative.
  • Add an ARIA live region at the app-shell level; wire task-lifecycle + toast announcements to it.
  • Confirm every interactive element has a focusable affordance (no <div onClick> without role=button).
  • Axe scan via Playwright — zero violations on Monitor, Pipeline, Planner, Board, Agents pages.
  • bun run qa clean.

Out of scope

  • Screen-reader voice testing on macOS/NVDA — manual verification pass after this ships.

References

  • Mockup ticket — blocker.
  • apps/web/e2e/ — add axe smoke tests next to the existing Playwright specs.
## User story As an operator using the dashboard daily, I want full keyboard navigation, visible focus rings, and ARIA live-region announcements for async state changes (task started / finished / failed), so that the dashboard is usable without a mouse and state changes are accessible. ## Dependencies - **Blocked by the a11y Penpot mockup** (sibling). ## Acceptance criteria - [ ] Global `:focus-visible` style per the mockup. - [ ] Implement the keyboard shortcut map globally (`g m`, `g a`, `/`, `?`, `esc`). - [ ] Implement Board drag-and-drop keyboard alternative. - [ ] Add an ARIA live region at the app-shell level; wire task-lifecycle + toast announcements to it. - [ ] Confirm every interactive element has a focusable affordance (no `<div onClick>` without `role=button`). - [ ] Axe scan via Playwright — zero violations on Monitor, Pipeline, Planner, Board, Agents pages. - [ ] `bun run qa` clean. ## Out of scope - Screen-reader voice testing on macOS/NVDA — manual verification pass after this ships. ## References - Mockup ticket — blocker. - `apps/web/e2e/` — add axe smoke tests next to the existing Playwright specs.
Collaborator

All acceptance criteria implemented and merged to main (commit 350fcca). QA clean on the implementation branch.

  • :focus-visible ring — src/styles/index.css
  • Global keymap (g m, g a, /, ?, Esc) — src/hooks/use-global-keymap.ts, wired in routes/__root.tsx
  • Keymap reference overlay — src/components/global-keymap-overlay.tsx
  • Board keyboard alternative (j/k columns, h/l cards, a/r/Enter shortcuts) — src/components/board/use-board-keymap.ts; DraggableCard carries role=button + tabIndex=0 + onKeyDown
  • ARIA live region — src/components/app-shell.tsx; src/lib/announce.ts; toast-store calls announce() on every push; task-lifecycle events surface via toasts
  • Axe smoke tests — e2e/a11y.spec.ts — zero violations on Monitor, Pipeline, Planner, Board, Agents
All acceptance criteria implemented and merged to `main` (commit `350fcca`). QA clean on the implementation branch. - `:focus-visible` ring — `src/styles/index.css` - Global keymap (`g m`, `g a`, `/`, `?`, `Esc`) — `src/hooks/use-global-keymap.ts`, wired in `routes/__root.tsx` - Keymap reference overlay — `src/components/global-keymap-overlay.tsx` - Board keyboard alternative (j/k columns, h/l cards, a/r/Enter shortcuts) — `src/components/board/use-board-keymap.ts`; `DraggableCard` carries `role=button` + `tabIndex=0` + `onKeyDown` - ARIA live region — `src/components/app-shell.tsx`; `src/lib/announce.ts`; toast-store calls `announce()` on every push; task-lifecycle events surface via toasts - Axe smoke tests — `e2e/a11y.spec.ts` — zero violations on Monitor, Pipeline, Planner, Board, Agents
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference
charles/claude-hooks#237
No description provided.