fix(a11y): unique nav landmarks + aria-current for active route #62

Open
KnallerKalle wants to merge 3 commits from feat/a11y-nav-landmarks into dev
KnallerKalle commented 2026-08-13 16:45:29 +00:00 (Migrated from github.com)

Plan

Continue the in-progress Release Hardening Accessibility audit pass ([~]) — audit and fix WCAG AA violations in the primary navigation (MobileNavigation), the second most-touched surface after the lesson player. The previous iteration (PR #56) established the jest-axe infra and fixed the AudioPlayer; this iteration covers the app's navigation chrome.

Outcome

Added a 4-assertion jest-axe accessibility suite for MobileNavigation (src/components/__tests__/MobileNavigation.a11y.test.tsx). Fixed two concrete WCAG AA violations:

  1. landmark-unique (WCAG 1.3.1 / 2.4.1): the mobile bottom bar and the desktop sidebar both rendered a <nav> element with no accessible name, so screen readers could not distinguish them. Added aria-label (main_navigation / sections_navigation, i18n into all 9 locales).
  2. Missing aria-current (WCAG 1.3.1 / 2.4.8 Location): the active route was indicated only by colour, with no semantic location cue. Added aria-current="page" to active links in both bars.

Also added ambient jest-axe type declarations (src/types/jest-axe.d.ts + src/types/vitest-jest-axe.d.ts) so bare tsc --noEmit passes locally (jest-axe ships no types of its own).

Impact on release goals

Release Hardening → "Accessibility audit pass" stays [~] (second component now audited + green; AudioPlayer was first via PR #56). A keyboard-only or screen-reader user can now orient themselves in the app's navigation: the two nav regions are announced distinctly, and the current page is spoken. This protects the D1→D7 retention window for assistive-tech users — they can navigate to the library and back to home without sighted help.

Blackbox

  • python3 scripts/blackbox_test.py --target testing → green (36/36)
  • Unit suite: 110/110 green (18 files; +4 new a11y tests)
  • tsc --noEmit → clean
  • axe reports zero violations on the rendered navigation

Six-perspectives check

  • Product: amplifies inclusive access (ATM is for every body); no dark patterns
  • Engineering: minimal diff (semantic attributes + i18n keys), tests cover the change, no security hole
  • Psychology: autonomy-supportive (screen-reader users regain independent navigation)
  • Biomechanics: n/a (no movement content touched)
  • Anatomy: n/a
  • Feldenkrais: inclusive by nature — the method is non-judgemental and for every body; accessible navigation embodies that

Risk

Low. Changes are semantic attributes (aria-label, aria-current) + i18n keys only; no visual or routing behaviour change for sighted mouse users. No Feldenkrais-principle surface touched.

Merge note (parallel work): both this branch and PR #56 add jest-axe to package.json/package-lock.json. Whichever merges first will require a mechanical rebase of the other — there is no logic conflict, only a lockfile resolution.

Checklist

  • Branch off latest dev (e8e268a)
  • Conventional Commits (test:, fix:, docs:)
  • Patchlog entry appended
  • Roadmap status updated
  • No secrets / no large binaries

This PR was created by an AI agent (OpenHands) on behalf of the ATM automation.

## Plan Continue the in-progress Release Hardening **Accessibility audit pass** (`[~]`) — audit and fix WCAG AA violations in the primary navigation (`MobileNavigation`), the second most-touched surface after the lesson player. The previous iteration (PR #56) established the jest-axe infra and fixed the AudioPlayer; this iteration covers the app's navigation chrome. ## Outcome Added a 4-assertion jest-axe accessibility suite for `MobileNavigation` (`src/components/__tests__/MobileNavigation.a11y.test.tsx`). Fixed two concrete WCAG AA violations: 1. **`landmark-unique` (WCAG 1.3.1 / 2.4.1):** the mobile bottom bar and the desktop sidebar both rendered a `<nav>` element with no accessible name, so screen readers could not distinguish them. Added `aria-label` (`main_navigation` / `sections_navigation`, i18n into all 9 locales). 2. **Missing `aria-current` (WCAG 1.3.1 / 2.4.8 Location):** the active route was indicated only by colour, with no semantic location cue. Added `aria-current="page"` to active links in both bars. Also added ambient jest-axe type declarations (`src/types/jest-axe.d.ts` + `src/types/vitest-jest-axe.d.ts`) so bare `tsc --noEmit` passes locally (jest-axe ships no types of its own). ## Impact on release goals Release Hardening → **"Accessibility audit pass" stays `[~]`** (second component now audited + green; AudioPlayer was first via PR #56). A keyboard-only or screen-reader user can now orient themselves in the app's navigation: the two nav regions are announced distinctly, and the current page is spoken. This protects the D1→D7 retention window for assistive-tech users — they can navigate to the library and back to home without sighted help. ## Blackbox - [x] `python3 scripts/blackbox_test.py --target testing` → **green (36/36)** - [x] Unit suite: **110/110 green** (18 files; +4 new a11y tests) - [x] `tsc --noEmit` → clean - [x] axe reports zero violations on the rendered navigation ## Six-perspectives check - [x] Product: amplifies inclusive access (ATM is for every body); no dark patterns - [x] Engineering: minimal diff (semantic attributes + i18n keys), tests cover the change, no security hole - [x] Psychology: autonomy-supportive (screen-reader users regain independent navigation) - [x] Biomechanics: n/a (no movement content touched) - [x] Anatomy: n/a - [x] Feldenkrais: inclusive by nature — the method is non-judgemental and for every body; accessible navigation embodies that ## Risk Low. Changes are semantic attributes (`aria-label`, `aria-current`) + i18n keys only; no visual or routing behaviour change for sighted mouse users. No Feldenkrais-principle surface touched. **Merge note (parallel work):** both this branch and PR #56 add `jest-axe` to `package.json`/`package-lock.json`. Whichever merges first will require a mechanical rebase of the other — there is **no logic conflict**, only a lockfile resolution. ## Checklist - [x] Branch off latest `dev` (`e8e268a`) - [x] Conventional Commits (`test:`, `fix:`, `docs:`) - [x] Patchlog entry appended - [x] Roadmap status updated - [x] No secrets / no large binaries --- _This PR was created by an AI agent (OpenHands) on behalf of the ATM automation._
This pull request has changes conflicting with the target branch.
  • .development/automation-state.json
  • .development/patchlog.md
  • .development/roadmap.md
  • package-lock.json
  • src/components/MobileNavigation.tsx
View command line instructions

Manual merge helper

Use this merge commit message when completing the merge manually.

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin feat/a11y-nav-landmarks:feat/a11y-nav-landmarks
git switch feat/a11y-nav-landmarks

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch dev
git merge --no-ff feat/a11y-nav-landmarks
git switch feat/a11y-nav-landmarks
git rebase dev
git switch dev
git merge --ff-only feat/a11y-nav-landmarks
git switch feat/a11y-nav-landmarks
git rebase dev
git switch dev
git merge --no-ff feat/a11y-nav-landmarks
git switch dev
git merge --squash feat/a11y-nav-landmarks
git switch dev
git merge --ff-only feat/a11y-nav-landmarks
git switch dev
git merge feat/a11y-nav-landmarks
git push origin dev
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Kalle/ATM!62
No description provided.