dorfteich/docs/architecture/adr/0017-accessibility-by-default.md
Claude Fable 5 858909564e
All checks were successful
CD / Build and push images (push) Successful in 1m12s
CD / Deploy to Test (push) Successful in 11s
CD / Smoke tests against Test (push) Successful in 1m13s
CD / Promote to Int (push) Successful in 11s
CI / Lint, typecheck, test (push) Successful in 4m45s
CI / Build container images (push) Has been skipped
CI / Auth e2e pack (push) Successful in 7m15s
CI / Import/export fidelity gate (push) Successful in 56s
Release / Build release images and notes (push) Successful in 1m11s
Release / Release-candidate operations QA (push) Successful in 44s
Prod deploy / Deploy the released images to Prod (push) Successful in 16s
docs: ADR 0017 — Barrierefreiheit als Standard-Anforderung
Jede künftige UI-Änderung entwickelt Barrierefreiheit direkt mit
(Stefans Vorgabe nach Abschluss des WCAG-2.1-AA-Audits): verbindliche
Checkliste als ADR, Kurzfassung in CLAUDE.md für jede Dev-Session,
Eintrag im ADR-Index.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGM8jo3hwoV9wsCVGfy8iq
2026-07-21 17:17:26 +02:00

73 lines
3.6 KiB
Markdown
Raw Permalink 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.

# ADR 0017: Accessibility (WCAG 2.1 AA) as a default requirement
- Status: accepted
- Date: 2026-07-21
## Context
A full WCAG 2.1 AA audit (July 2026) found a solid baseline — enforced
accessible names on `IconButton`, the implicitly labelling `Field`
primitive, localized ARIA labels, a clean landmark structure — but also
systemic gaps that had accumulated because accessibility was checked
after the fact rather than built in: dialogs without focus management, a
hard-coded document language, broken listbox semantics, page-level
horizontal scrolling at 320 px viewport width. All findings were fixed in
issues #162#171; an axe-core smoke pack (`apps/web/e2e/a11y.spec.ts`)
now pins the core screens in CI.
Retro-fitting accessibility is far more expensive than building it in.
This ADR makes it a default requirement for every future feature.
## Decision
**Every user-facing change ships accessible.** Concretely, a feature is
not done until it satisfies this checklist:
1. **Reuse the accessible primitives.** Icon-only controls go through
`IconButton` (enforces a name); form controls go through `Field`
(label + `aria-describedby`/`aria-invalid` wiring); dialogs use
`useModalFocus` (focus trap, initial focus, focus return) plus
`aria-labelledby` on their heading. Do not hand-roll parallels.
2. **Keyboard first.** Everything reachable and operable by keyboard,
visible focus, Escape closes overlays, no focus loss on unmount. New
single-key shortcuts must respect the "disable single-key shortcuts"
setting (`lib/single-key-shortcuts.ts`).
3. **Name, role, value.** New widgets carry correct roles and
localized (de+en) accessible names; state via `aria-expanded`,
`aria-selected`, `aria-pressed` etc. Decorative icons stay
`aria-hidden`.
4. **Both render paths.** Anything that renders content must behave
identically in the editor/NodeView path AND the `docToHtml`/server
path (public view, comments, previews) — including labels and list
semantics. Remember: `page_content_cache` rolls out `docToHtml`
changes lazily (on next persist).
5. **Color and contrast.** Use the design tokens; text ≥ 4.5:1, UI
boundaries and icons ≥ 3:1 (`--color-border-input` exists for field
borders; `--color-favorite` is icon-only). Color is never the only
cue. Dark-rendered surfaces (public shell) keep their checked colors.
6. **Reflow.** New layouts must not force page-level horizontal
scrolling at 320 px (flex/grid children need `min-width: 0`;
intrinsically wide content scrolls in its own focusable container).
7. **Motion and time.** Respect `prefers-reduced-motion`; no
auto-updating or auto-dismissing content faster than users can
perceive it.
8. **Extend the CI pack.** A new core screen or a new interaction
pattern gets added to `apps/web/e2e/a11y.spec.ts` (axe, WCAG A/AA
tags, empty allowlist — additions to the allowlist need a written
justification in the spec).
Code review and issue acceptance criteria treat violations of this
checklist like functional defects, not polish.
## Consequences
- New features cost slightly more up front and no longer accumulate an
accessibility backlog; the July 2026 audit stays the last big one.
- The axe CI pack fails builds on regressions of the fixed state; specs
may need locator updates when accessible names are added (a11y labels
can make `getByLabel` matchers ambiguous — scope them).
- The full audit report (methodology, per-criterion matrix, measurement
harness) lives in the operator's workspace
(`doku/audit-barrierefreiheit-2026-07.md`) and can be re-run after
larger UI changes.