--- status: accepted date: 2026-04-30 decision-makers: R&D Lead tags: [accessibility, frontend, process] --- # Accessibility baseline — WCAG 2.2 AA + targeted AAA, Angular CDK + spartan-ng + Tailwind, APF panel testing ## Context and Problem Statement The host organisation is **APF France Handicap**. Accessibility is the organisation's core mission, not a compliance checkbox. A meaningful proportion of the portal's users will be in situations of disability — visual, motor, cognitive, hearing — and will rely on assistive technologies (screen readers, switch controls, eye tracking, voice control, head pointers, mouth sticks). The portal's accessibility quality is therefore a **product attribute**, not a downstream concern. The default WCAG 2.2 AA baseline applicable to enterprise portals would _under-serve_ this user base. We need to fix: - the conformance target (WCAG level + targeted enhancements); - the implementation stack (component library, primitives, styling); - the user-preferences surface (contrast, text size, motion, etc.) the portal must offer; - the testing strategy, including manual testing with users from APF's internal network; - the CI gates that prevent regression; - the legal-disclosure surface (the EU Accessibility Act–required accessibility statement). This ADR fixes the framework. Concrete component-by-component implementation lands as the scaffold and features arrive. ## Decision Drivers - APF's mission elevates accessibility from "compliance" to "product". - European Accessibility Act (EAA, in application since June 2025) makes WCAG 2.2 AA a legal floor in the EU; the portal will publish an accessibility statement and accept regression as a defect, not as a backlog item. - RGAA 4.1 (French national standard, derived from WCAG) is the operational reference for accessibility audits in France; alignment is necessary to be auditable by French experts (including APF's own). - The user base extends beyond screen-reader users: switch controls, eye tracking, voice control, cognitive load tolerance — all must be considered. - The technical stack is locked on Angular ([ADR-0004](0004-frontend-stack-angular-csr-zoneless-signals.md)). Component-library choice must therefore be Angular-native or framework-agnostic. - The dual-audience design ([ADR-0008](0008-identity-model-entra-workforce-dual-audience.md)) means a11y must be uniform across audiences — workforce and (future) customer users alike. - Anti-bricolage: no hand-rolled a11y where a maintained library exists. ## Considered Options ### Conformance target - WCAG 2.2 **AA** baseline (EU EAA legal floor). - WCAG 2.2 **AA + targeted AAA** on criteria with high impact for APF's user base. (Chosen.) - WCAG 2.2 **AAA** uniform. ### UI component stack - Angular Material (Angular CDK + Material visual layer). - **Angular CDK + spartan-ng + Tailwind.** (Chosen — see also `notes/argumentaire-stack-ui-spartan-cdk-tailwind.md` for the team-internal rationale.) - Custom-on-Angular-CDK only (no spartan-ng). - React-ecosystem libs (shadcn/ui, dice-ui, animate-ui). ### User-preferences scope - None (rely on browser/OS prefs). - `prefers-reduced-motion` only. - **Full preferences panel** — contrast modes, text size, motion, spacing, simplified UI. (Chosen.) ### Testing strategy - Automated only (axe-core + lint). - Automated + external annual audit. - **Automated + manual screen-reader/keyboard/switch testing + APF user panel cadence + annual internal audit.** (Chosen.) ### Documentation surface - Internal docs only. - **Public accessibility statement page (legal EAA requirement) + internal patterns library.** (Chosen.) ## Decision Outcome ### Conformance target **WCAG 2.2 AA** as the universal baseline. **AAA** applied on the criteria that materially affect APF's user base: | AAA criterion | What it adds vs AA | Why APF | | ------------------------------------- | -------------------------------------------------------------------------------- | ------------------------------------------ | | **1.4.6 Contrast (Enhanced)** | 7:1 normal text / 4.5:1 large text (vs 4.5:1 / 3:1 at AA) | Low-vision users are a primary audience | | **2.2.3 No Timing** | No time limits except where essential | Cognitive load and motor speed vary widely | | **2.3.3 Animation from Interactions** | All interaction-driven animation can be disabled | Vestibular and cognitive disorders | | **3.1.5 Reading Level** | Content readable at lower secondary level _or_ a simpler alternative is provided | Cognitive accessibility | | **1.4.8 Visual Presentation** | User control over text formatting (line spacing, paragraph spacing, line length) | Dyslexia, low vision | | **2.4.9 Link Purpose (Link Only)** | Each link's purpose understandable from its text alone (no surrounding context) | Screen-reader navigation by link list | | **3.3.5 Help** | Context-sensitive help available where needed | Cognitive accessibility | The remaining AAA criteria (e.g. 1.2.6 Sign Language, 1.2.8 Media Alternative) are **not** uniformly required — they apply where the corresponding content type appears, and are addressed case by case. **RGAA 4.1** alignment is maintained as the audit reference for French experts (APF, CNIL audits, public-sector partners). ### User-preferences panel The portal exposes a **first-class user-preferences panel** accessible from any page (keyboard-discoverable, screen-reader-announced, persisted in the user's session per [ADR-0010](0010-session-management-redis.md)): | Preference | Options | Default | | ------------------------ | --------------------------------------------------------------------------------------------------- | --------------------------------------- | | Contrast mode | Standard (AA-compliant) / Enhanced (AAA, 7:1) / Maximum (high-contrast OS-style, monochrome) | Standard | | Text size | 100 % / 125 % / 150 % / 175 % / 200 % | 100 % | | Motion | Full / Reduced / None | inherited from `prefers-reduced-motion` | | Text spacing | Default / Generous (line-spacing 1.8, paragraph-spacing 2×, letter-spacing 0.12em) | Default | | Cognitive simplification | Off / On (reduces secondary chrome, larger primary actions, easier-to-read summaries when authored) | Off | | Reading focus | Off / Line-by-line | Off | Preferences are saved per user; an unauthenticated default is read from browser preferences (`prefers-reduced-motion`, `prefers-contrast`, etc.). Changing a preference takes effect immediately, no page reload. ### Component stack **Angular CDK + spartan-ng + TailwindCSS**. See [`notes/argumentaire-stack-ui-spartan-cdk-tailwind.md`](../notes/argumentaire-stack-ui-spartan-cdk-tailwind.md) for the full rationale produced for the dev team. Summary: - **Angular CDK** (`@angular/cdk`) — primitives accessibility layer maintained by Google's Angular Material team. Equivalent role to Radix UI in React. Provides `Overlay`, `FocusTrap`, `FocusMonitor`, `LiveAnnouncer`, `A11yModule`, `ListKeyManager`, `Drag and Drop`, etc. Battle-tested since 2017. - **spartan-ng** (https://www.spartan.ng/) — copy-paste component layer built on Angular CDK, styled with Tailwind. Components are checked into our repo (`libs/shared/ui/`) and modified freely. Equivalent role to shadcn/ui in React. - **Tailwind CSS** — utility-first styling. Tokens for colour, spacing, contrast tiers live in `libs/shared/tokens/`. The contrast tiers map directly to the user preference modes above. Angular Material is **rejected** because its visual design system (Material Design) is opinionated in ways that clash with both APF branding and the multi-tier contrast requirements. React-ecosystem libraries (shadcn/ui, dice-ui, animate-ui) are rejected as incompatible with the Angular stack ([ADR-0004](0004-frontend-stack-angular-csr-zoneless-signals.md)). ### Concrete patterns to enforce | Concern | Rule | | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Sémantique HTML | `
`, `
`, `