feat(a11y): WCAG audit fixes — skip link, focus-visible, header landmark, WCAG 2.2 coverage#712
Open
grzanka wants to merge 5 commits into
Open
feat(a11y): WCAG audit fixes — skip link, focus-visible, header landmark, WCAG 2.2 coverage#712grzanka wants to merge 5 commits into
grzanka wants to merge 5 commits into
Conversation
Adds a visually-hidden-until-focused skip link as the first focusable element in the layout, with a matching #main-content target on <main>. Keyboard and screen-reader users can now bypass the ~8 header controls on every route. Covered by a new e2e assertion. Closes #708
Guarantees a consistent, visible focus indicator on all interactive elements. Uses :where() for zero specificity so existing component-level focus styles still win, and excludes tabindex="-1" skip targets. Closes #709
…WCAG 1.3.1) The masthead is now a <header> (banner role) instead of a bare <nav>. The navigation landmark is scoped to just the Calculator/Plot/Docs route tabs and given an accessible name, so export/share/mode controls no longer live inside the navigation landmark. data-testid hooks preserved. Closes #710
… and contrast - axe e2e now runs the wcag22aa tag set (adds target-size / SC 2.5.8) - clear-override buttons get a 24px hit area to satisfy SC 2.5.8 - global prefers-reduced-motion rule neutralizes Tailwind motion (SC 2.3.3) - darken --muted-foreground (0.47 → 0.44) for AA contrast headroom (SC 1.4.3) Closes #711
Contributor
There was a problem hiding this comment.
Pull request overview
Addresses remaining gaps from the WCAG accessibility audit by adding an explicit bypass mechanism, a global focus-visible fallback, improved landmark semantics in the masthead, and expanding automated checks to include WCAG 2.2 AA coverage.
Changes:
- Added a “Skip to content” link targeting a focusable
<main id="main-content" tabindex="-1">, plus an E2E regression assertion. - Added global
:focus-visiblefallback styling and a globalprefers-reduced-motion: reduceneutralization rule; darkened--muted-foregroundfor improved contrast headroom. - Scoped the primary navigation landmark to route tabs only (
<header>+<nav aria-label="Primary">) and increased hit area for small clear-override icon buttons.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/e2e/accessibility.spec.ts | Expands axe tags to include wcag22aa and adds a dedicated skip-link regression test. |
| src/routes/+layout.svelte | Adds skip link + main-content target; converts masthead to <header> and scopes <nav> to route tabs. |
| src/lib/components/advanced-options-panel.svelte | Enlarges clear-override icon button hit areas to meet target-size minimums. |
| src/app.css | Adds global :focus-visible fallback, reduced-motion overrides, and adjusts --muted-foreground for contrast headroom. |
| docs/ai-logs/README.md | Adds an index entry for the new WCAG audit session log. |
| docs/ai-logs/2026-06-05-wcag-accessibility-audit.md | Adds a detailed session log documenting the audit findings and implemented fixes. |
| CHANGELOG-AI.md | Adds a Stage 8 accessibility changelog entry referencing the session log. |
Comment on lines
24
to
26
| const results = await new AxeBuilder({ page }) | ||
| .withTags(["wcag2a", "wcag2aa"]) | ||
| .withTags(["wcag2a", "wcag2aa", "wcag22aa"]) | ||
| // Bits UI Combobox places the search <input role="combobox"> inside |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes the gaps found in the WCAG accessibility audit. The app was already
well-instrumented (axe-core e2e in CI, live regions, focus traps,
aria-current,48px route-tab targets, plot
role="img"), so this PR fixes the remainingconcrete gaps plus a coverage blind spot. One commit per issue.
:focus-visiblefallback<header>banner landmark,<nav>scoped to route tabsDetails
focusable element, targeting
<main id="main-content" tabindex="-1">. Added adedicated e2e assertion (first Tab focuses it, Enter moves focus to
<main>)because axe's
bypassrule does not reliably detect a missing skip link.:where(...):focus-visiblerule inapp.css. Zerospecificity so existing component focus styles still win; excludes
tabindex="-1"skip targets.<header>(banner);<nav aria-label="Primary">wraps only the route tabs, so export/share/mode controls leave the navigation
landmark. All
data-testidhooks preserved.wcag22aatag set (addstarget-size/SC 2.5.8); the two clear-override icon buttons get a 24px hit area; a global
prefers-reduced-motionrule neutralizes Tailwind motion;--muted-foregrounddarkened 0.47 → 0.44 for AA contrast headroom.
Testing
pnpm lint— cleanpnpm check(svelte-check + tsc) — 0 errorspnpm test— 1697 pass. The only failures are inguard-forbidden-files.test.ts,which spawn nested
git commits that hit the sandbox commit-signing server(environmental, unrelated to these changes).
wcag22aatag and skip-link test) runs in CI; itcould not be executed in this environment (no built WASM / Playwright browsers),
so CI is the final verifier for
target-size.Closes #708, closes #709, closes #710, closes #711
https://claude.ai/code/session_01TxkfT8pSyshPRerfofkoVf
Generated by Claude Code