One-time prettier --write so the new format:check CI gate starts green. .prettierignore excludes generated (api-client.ts, documentation.json), vendored (public/cibg-huisstijl), and backend (dotnet format owns it). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
3.6 KiB
3.6 KiB
WP-17 — App-level a11y: route focus/scroll, template lint, WCAG checklist + MDX
Status: todo Phase: 4 — a11y
Why
Three app-level gaps close the WCAG story:
- No route-change focus/scroll management —
app.config.tshas onlyprovideRouter(routes, withViewTransitions()); after navigation, focus stays wherever it was and scroll position is unmanaged. (The wizard manages focus within steps; the skip link is the only cross-page mechanism.) - No template a11y linting —
@angular-eslintis entirely absent. - User decision: a manual WCAG checklist documents what automation can't test.
Read first
src/app/app.config.tseslint.config.mjs,package.jsonsrc/app/shared/layout/shell/shell.component.ts(#maintarget),page-shell/page-shell.component.ts(candidate focus target)
Decisions (pre-made, don't relitigate)
- Scroll:
withInMemoryScrolling({ scrollPositionRestoration: 'enabled' }). - Focus: on
NavigationEnd, move focus to the new page'sh1(or#mainfallback,tabindex="-1"), deferred viaafterNextRenderso it coexists with view transitions; skip the initial load. Implement as a small root service/effect wired inapp.config.ts— not per page. - Lint:
angular-eslintat the version matching Angular 22 (~v21+ — checknpm view angular-eslint peerDependencies), withprocessInlineTemplates(this repo has no.htmltemplates). Rules:alt-text,label-has-associated-control,interactive-supports-focus,click-events-have-key-events,valid-aria,elements-content. Verify the processor fires by planting a known-bad pattern before trusting green. - The checklist is a living doc with per-page status columns — not prose.
Files
src/app/app.config.ts+ a new smallshared/focus-on-navigation serviceeslint.config.mjs,package.json(angular-eslint)- Any template the new lint rules flag
- New
docs/wcag-checklist.md - New
src/docs/a11y.mdx— titleFoundations/Accessibility
Steps
- Router scroll + focus service; manual keyboard smoke (tab through, navigate, confirm focus lands on the new page's heading).
- Add angular-eslint; enable the template rules on inline templates; plant a bad pattern, see it fail, remove it; fix real hits.
docs/wcag-checklist.md: manual checks per page (dashboard, wizards, brief, login) — keyboard walk & focus order, no traps, 200% zoom/reflow, NVDA or VoiceOver pass, visible focus, error announcement; status columns (page × check).src/docs/a11y.mdx: the layered approach — axe gate (WP-01) + template lint + play tests (WP-16) + manual checklist; the alert-role rationale; where thea11y.disableskip register lives and its rules.
Acceptance criteria
- Navigating between routes moves focus to the new page's heading; scroll resets; view transitions still play.
- Template a11y rules active and proven to fire; lint green.
- Checklist checked in with an initial pass filled in for the dashboard at minimum.
a11y.mdxrenders; links to checklist and WP-01 skip rules.
Verification
GREEN + npm run test-storybook:ci. Manual: keyboard-only walk of
login → dashboard → wizard → brief.
Out of scope
Full manual audit of every page (the checklist enables it; filling it beyond the dashboard is ongoing work, not this WP).
Risks
- angular-eslint's inline-template processor silently not running → the planted-violation step is mandatory.
- Focus-move vs
withViewTransitionstiming →afterNextRender+ test in a real browser (npm start), not just unit-level.