Files
marketplaces/docs/ACCESSIBILITY_REPORT.md
sdarbinyan f5f431620e docs: add ACCESSIBILITY_REPORT.md for RC A11Y-01
Consolidates the 3 WCAG 2.1 AA audit commits (storefront, builder,
backoffice): skip links, keyboard-operable DnD fallbacks, dialog
focus-trap fixes, contrast fixes, form labeling, live-region
announcements, combobox/tablist ARIA. Flags remaining brand-color
contrast failures needing theme-owner sign-off, not fixed unilaterally.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-24 09:19:18 +04:00

62 lines
6.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Accessibility Report — RC A11Y-01
WCAG 2.1 AA audit + fixes across the whole application: Storefront, Builder (Project Editor), Backoffice (Admin). No redesign, no layout changes, no route/business-logic changes. Three sequential commits on branch `B2B` (not pushed):
| Commit | Scope |
|---|---|
| `fb1afb7` | Storefront |
| `a03260e` | Builder |
| `565fd9b` | Backoffice |
`npm run build` verified green after every commit. `npx tsc --noEmit` clean throughout.
This audit goes deeper than the prior composition pass (`docs/UI-COMPOSITION-REVIEW.md` — skeletons/empty-states/`scope="col"`) into categories that pass didn't cover: skip links, keyboard-operable drag-and-drop, dialog focus management, color contrast ratios, form label association, live-region announcements, and combobox/tablist ARIA patterns.
## Fixes by area
### Storefront (`fb1afb7`)
- **Skip link** — didn't exist anywhere in the app. Added as the first focusable element (`app.html`), targeting a new `#main-content` landmark. Single most commonly-missing WCAG 2.4.1 fix, present nowhere before this.
- **Keyboard/focus traps** — header mobile menu kept its items tabbable/screen-reader-reachable while visually collapsed; fixed via `visibility` + delayed transition. Header's search input had no keyboard activation path.
- **Dialog accessibility** — cart's custom payment/bank-payment modals had *no* focus-trap, Escape handling, or return-focus, despite prior docs assuming `app-dialog` coverage — they're custom, not `app-dialog`. Ported the confirmed-correct `app-dialog` pattern directly onto them.
- **Screen-reader announcements** — payment status screens (creating/waiting/success/error/timeout) got `role="status"`/`role="alert"` + `aria-live`.
- **Search combobox** — added `role="combobox"`/`aria-autocomplete`/`aria-controls`/`aria-activedescendant` so the existing arrow-key navigation is actually announced to screen readers (previously silent).
- **Tabs** — product tabs had `role="tab"` with no `tablist`/`tabpanel` wrapper; completed the pattern.
- **Forms** — review-form errors now `aria-describedby` + `role="alert"`; `aria-required` on review textarea and delivery select.
- **Icons** — `app-icon` (shared, app-wide) claimed "decorative by default" in its own contract but never actually applied `aria-hidden` — fixed for real, affects every icon usage across the app.
- **Contrast** — `--text-light` measured 3.39:1 (dexar theme) / 2.54:1 (lavero/novo) against the 4.5:1 requirement. Switched the 2 in-scope usages to `--text-secondary` (7.56:1 / 4.55:1).
### Builder (`a03260e`)
- **Skip link** — Builder routes render outside the storefront app-shell entirely (bare `<router-outlet>`), so the storefront fix didn't cover it. Added separately with its own `#builder-main-content` landmark.
- **Keyboard-operable drag-and-drop (WCAG 2.1.1)** — Homepage section's block list and Footer section's columns/links use Angular CDK drag-drop with zero keyboard equivalent. Added move-up/move-down button fallbacks (Navigation and Widgets sections already had this from an earlier sprint).
- **Undefined `--color-primary` token** — same bug class as the prior composition pass, missed there: 7 usages across 3 files silently fell back to hardcoded hex, never responding to tenant theming. Remapped to the real `--primary-color` token.
- **Forms** — color-picker's `<input type="color">` swatches (8 instances) had no accessible name; new-locale input relied on placeholder text alone (invisible to screen readers once a value is typed).
- **Screen-reader announcements** — save-bar status/draft-restored notice and media-picker upload errors had no `aria-live`/`role`.
### Backoffice (`565fd9b`)
- **Sidebar nav mislabeled** — `<nav aria-label>` reused the "Dashboard" translation key, so the entire admin sidebar announced itself as "Dashboard" to screen readers regardless of which section a user was in. New dedicated label.
- **Categories tree drag-and-drop (WCAG 2.1.1)** — native HTML5 DnD reorder had no keyboard path; arrow keys only expand/collapse/select. Added move-up/move-down buttons per row, boundary-disabled, reusing the existing `reorder()` facade method (no logic change).
- **Screen-reader loading announcements** — `app-skeleton` is `aria-hidden` by design (correct for visual-only use), but 9 list pages (Products, Categories, Customers, Orders, Transactions, Users, Reviews, Monitoring, Analytics) had *no* accompanying live-region text, so screen-reader users got total silence during loads. Added `role="status"`/`aria-live="polite"`/`aria-busy` + sr-only text.
- **Table row headers** — `scope="col"` was already complete from the prior pass; added `scope="row"` to the primary identifying cell on 9 tables (product/category/customer name, order/transaction number, etc.) with matching CSS resets so the shared table's header styling doesn't visually leak onto them.
- **Dialogs, forms, `scope="col"`** — already correct across the board (all route through `app-dialog`/`app-form-field`), confirmed not re-touched.
## Deliberately not fixed (flagged for a design-decision follow-up)
Failing color contrast that is a **genuine brand/semantic color**, not a bug — fixing these means changing what the palette looks like, which needs sign-off from whoever owns the theme, not an accessibility pass's unilateral call:
- `--border-color` fails 3:1 UI-component contrast in every theme (1.241.42:1) — pervasive token, hundreds of usages across the whole app.
- `--success-color`/`--warning-color`/`--error-color`/`--info-color` fail 4.5:1 when used as plain text-on-white in a handful of places.
- Builder save-bar's warning/error/info text-on-white — same category.
Other flagged items:
- Locale-tabs' partial tablist pattern (no roving-tabindex) — accepted precedent across all 3 surfaces, not fixed in any of them.
- No toast/success-error notification system exists anywhere in the app (backoffice save/delete has nothing to announce — a feature gap, not an accessibility regression of existing UI).
- Dashboard's per-card mini-skeletons — would need a page-level live region rather than per-widget, deferred.
- A handful of already-known partial-widget gaps carried from `docs/UI-COMPOSITION-REVIEW.md` (monitoring events table, notifications dropdown, analytics `lowStockProducts` missing skeleton) — pre-flagged, not newly found, not re-litigated here.
## Verification
`tsc --noEmit` and `npm run build` green after all three commits. No live browser/screen-reader session available this session — recommend a manual pass with an actual screen reader (NVDA/VoiceOver) and automated tooling (axe-core/Lighthouse a11y score) against a deployed build before the client demo referenced in `docs/FRONTEND-ROADMAP.md`, since static-analysis ARIA correctness doesn't guarantee real-world screen-reader UX.