|
| 1 | +# WCAG 2.1 AA Accessibility Audit |
| 2 | + |
| 3 | +Issue: [wraith-protocol/www#21](https://github.com/wraith-protocol/www/issues/21) |
| 4 | + |
| 5 | +Date: 2026-06-26 |
| 6 | + |
| 7 | +Scope: homepage and press page source audit, with implemented Critical and Serious fixes in this PR. |
| 8 | + |
| 9 | +## Tools |
| 10 | + |
| 11 | +- `vitest-axe` / `axe-core` smoke gate for the rendered homepage. |
| 12 | +- Keyboard navigation pass for skip link, desktop links, mobile menu, code tabs, comparison tabs, copy buttons, and press kit controls. |
| 13 | +- Color contrast review for small mono labels on `surface` and `surface-container` backgrounds. |
| 14 | +- Screen-reader semantics review for landmarks, heading hierarchy, tab widgets, icon/utility buttons, and live copy status messaging. |
| 15 | +- VoiceOver run-through checklist documented below for the corrected landmark, heading, tab, and button names. |
| 16 | + |
| 17 | +## Findings |
| 18 | + |
| 19 | +| Severity | WCAG 2.1 AA Criterion | Element / selector | Finding | Fix in this PR | |
| 20 | +| -------- | --------------------------------------------- | ----------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | |
| 21 | +| Critical | 2.4.1 Bypass Blocks | `App`, page header/navigation | Keyboard users had no skip link to bypass the fixed navigation. | Added a visible-on-focus skip link targeting `main#main-content`. | |
| 22 | +| Serious | 2.4.7 Focus Visible | Global links and buttons | Interactive controls relied on browser defaults or visual hover states, which were inconsistent against the dark UI. | Added a global `:focus-visible` outline using the blue accent token. | |
| 23 | +| Serious | 1.4.3 Contrast (Minimum) | `.text-outline` small mono labels on dark backgrounds | The previous outline text color was too dim for repeated 9-13px labels. | Raised outline and outline-variant token contrast while preserving the dark visual system. | |
| 24 | +| Serious | 4.1.2 Name, Role, Value | `Header` mobile menu button and panel | Mobile menu state was not exposed, Escape did not dismiss it, and focus could leave the open menu unexpectedly. | Added `aria-expanded`, `aria-controls`, specific open/close labels, Escape dismiss, focus return, and a focus trap. | |
| 25 | +| Serious | 4.1.2 Name, Role, Value | `Hero` code sample tabs | Visual tabs were plain buttons without tab roles, selected state, or arrow-key navigation. | Added `tablist`, `tab`, `tabpanel`, `aria-selected`, `aria-controls`, roving tab index, and Arrow/Home/End key handling. | |
| 26 | +| Serious | 4.1.3 Status Messages | `Hero` and `Press` copy buttons | Copy actions changed visible text but did not reliably announce completion to assistive tech. | Added accessible button names and polite live-region copy status. | |
| 27 | +| Serious | 4.1.2 Name, Role, Value | `Compare` detail filter tabs | Comparison filters were visually tabbed but lacked tab semantics and keyboard tab behavior. | Added semantic tablist/tabpanel relationships and roving keyboard navigation. | |
| 28 | +| Serious | 1.3.1 Info and Relationships | `Compare` table row labels | Row labels used `scope="row"` on `td`, which is invalid table semantics. | Converted protocol row labels to `th scope="row"`. | |
| 29 | +| Serious | 2.5.3 Label in Name / 4.1.2 Name, Role, Value | `Press` brand color swatches | Swatches relied on `title` and visual color text, leaving button purpose ambiguous. | Added explicit labels such as `Copy Surface brand color #0e0e0e`. | |
| 30 | +| Minor | 1.1.1 Non-text Content | Header/footer logo images | Logo image alt text repeated adjacent Wraith text inside the same link/brand block. | Marked repeated logo images decorative with empty `alt`. | |
| 31 | + |
| 32 | +## Follow-up Issues |
| 33 | + |
| 34 | +| Severity | WCAG 2.1 AA Criterion | Element / selector | Recommendation | |
| 35 | +| -------- | --------------------------------- | ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | |
| 36 | +| Moderate | 1.3.1 Info and Relationships | Comparison table on narrow screens | Consider adding an off-screen caption that summarizes horizontal scrolling and comparison purpose. | |
| 37 | +| Moderate | 2.4.4 Link Purpose | Repeated external CTA links | Consider making repeated external CTA link purpose more specific where context is sparse. | |
| 38 | +| Minor | 2.3.3 Animation from Interactions | Decorative pulsing dots | Current reduced-motion rules cover reveal animations. Consider removing pulse animations under `prefers-reduced-motion` as a polish follow-up. | |
| 39 | + |
| 40 | +## VoiceOver Run-through Notes |
| 41 | + |
| 42 | +- Landmark order: skip link, banner/navigation, main content, footer. |
| 43 | +- Homepage heading structure: one `h1` followed by section-level `h2` headings. |
| 44 | +- Mobile menu button announces open/closed state and returns focus to the trigger on Escape. |
| 45 | +- Hero code examples announce as a tab group with selected file tab and associated code panel. |
| 46 | +- Comparison details announce as a tab group with selected filter and associated panel. |
| 47 | +- Copy controls have action-specific labels and announce successful copy through a polite status region. |
| 48 | + |
| 49 | +## CI Gate |
| 50 | + |
| 51 | +The homepage accessibility smoke gate is implemented in `src/__tests__/a11y.test.tsx` and runs with: |
| 52 | + |
| 53 | +```bash |
| 54 | +pnpm test:a11y |
| 55 | +``` |
| 56 | + |
| 57 | +This test renders the homepage, runs axe, and verifies the primary mobile-menu and copy-control keyboard paths. |
0 commit comments