|
| 1 | + feat/accessibility-audit |
| 2 | +# Contributing to NiffyInsur |
| 3 | + |
| 4 | +## Accessibility Testing |
| 5 | + |
| 6 | +Accessibility is a first-class requirement. Every PR that touches UI must pass the checks below before merge. |
| 7 | + |
| 8 | +### Automated axe checks (CI) |
| 9 | + |
| 10 | +The `accessibility` CI job runs `@axe-core/playwright` against the quote, policy, claims, and vote routes. **No critical violations are permitted.** The job uploads a Playwright report as an artifact on failure. |
| 11 | + |
| 12 | +Run locally: |
| 13 | + |
| 14 | +```bash |
| 15 | +cd frontend |
| 16 | +npm install |
| 17 | +npm run build |
| 18 | +npx playwright test tests/accessibility.spec.ts |
| 19 | +``` |
| 20 | + |
| 21 | +### Manual axe spot-check |
| 22 | + |
| 23 | +1. Install the [axe DevTools browser extension](https://www.deque.com/axe/devtools/). |
| 24 | +2. Open each targeted route: `/quote`, `/policy`, `/claims`, `/claims/<id>`. |
| 25 | +3. Run the full-page scan. Resolve any **critical** or **serious** violations before opening a PR. |
| 26 | + |
| 27 | +### Keyboard-only walkthrough |
| 28 | + |
| 29 | +Verify these flows using only the keyboard (no mouse): |
| 30 | + |
| 31 | +| Flow | Steps | |
| 32 | +|------|-------| |
| 33 | +| Get a quote | Tab through all form fields → submit → confirm quote preview updates | |
| 34 | +| Purchase policy | Complete all 4 wizard steps using Tab / Shift+Tab / Enter / Space | |
| 35 | +| File a claim | Complete all 4 wizard steps; confirm focus moves to new step heading on advance | |
| 36 | +| Cast a vote | Tab to Approve / Reject buttons → Enter to open confirm modal → Tab within modal → confirm or cancel | |
| 37 | +| Connect wallet | Tab to "Connect Wallet" button → Enter → confirm status announced | |
| 38 | + |
| 39 | +Focus must always be visible. After a modal opens, focus must move inside it. After a modal closes, focus must return to the trigger. |
| 40 | + |
| 41 | +### Screen reader spot-check (per major release) |
| 42 | + |
| 43 | +Test at minimum one major flow per release with a screen reader: |
| 44 | + |
| 45 | +- **macOS / iOS**: VoiceOver (`Cmd+F5` to toggle) |
| 46 | +- **Windows**: NVDA (free) or Narrator |
| 47 | +- **Android**: TalkBack |
| 48 | + |
| 49 | +Checklist: |
| 50 | +- [ ] Transaction status updates are announced (aria-live regions on wizard and policy pages) |
| 51 | +- [ ] Step changes in wizards are announced (focus moves to hidden `<h2>` with step name) |
| 52 | +- [ ] Quote preview updates are announced on the quote page |
| 53 | +- [ ] Vote tally countdown is announced via `aria-live="polite"` |
| 54 | +- [ ] Modal title is read when dialog opens |
| 55 | +- [ ] Icon-only buttons have accessible names (aria-label or sr-only text) |
| 56 | +- [ ] Claim status badges convey outcome via text/shape, not color alone |
| 57 | + |
| 58 | +### Reduced-motion |
| 59 | + |
| 60 | +Verify that setting `prefers-reduced-motion: reduce` (OS accessibility setting or DevTools emulation) stops all non-essential animations. Loading spinners should become static; slide/fade transitions should be instant. |
| 61 | + |
| 62 | +### Heading hierarchy |
| 63 | + |
| 64 | +Each page must have exactly one `<h1>`. Use the browser Accessibility Tree panel (DevTools → Accessibility) or the [HeadingsMap extension](https://rumoroso.bitbucket.io/headingsmap/) to verify a logical heading order with no skipped levels. |
| 65 | + |
| 66 | +### Landmarks |
| 67 | + |
| 68 | +Every page must have at minimum: `<main>`, `<nav>` (if navigation present), and `<footer>` (if present). Verify with the Accessibility Tree or axe. |
| 69 | + |
| 70 | +### Color contrast |
| 71 | + |
| 72 | +All text must meet WCAG AA contrast ratios (4.5:1 normal text, 3:1 large text). Use the axe scan or the browser color-contrast checker. Claim outcomes (Approved / Rejected / Pending) must not rely on color alone — shape indicators and text labels are required. |
| 73 | + |
| 74 | +### Adding new UI |
| 75 | + |
| 76 | +When adding new interactive components: |
| 77 | + |
| 78 | +1. Icon-only controls **must** have `aria-label` or a visually hidden label. |
| 79 | +2. Async state changes (transactions, loading) **must** update an `aria-live` region. |
| 80 | +3. Multi-step wizards **must** move focus to a step heading on step change. |
| 81 | +4. Modals **must** trap focus and return it to the trigger on close (Radix Dialog handles this automatically). |
| 82 | +5. Animations **must** respect `prefers-reduced-motion` via the global CSS rule in `globals.css`. |
| 83 | + |
1 | 84 | # Contributing |
2 | 85 |
|
3 | 86 | ## Soroban ABI golden vectors |
@@ -48,3 +131,4 @@ Before tagging a release: |
48 | 131 | - **Never** commit real private keys (Stellar secret keys start with `S`). |
49 | 132 | - Use only placeholder G-addresses and C-addresses in vector `inputs`. |
50 | 133 | - The CI job checks for secret-key patterns and will fail if any are found. |
| 134 | + main |
0 commit comments