# WCAG 2.2 AA — Admin + visual-edit host

EdgeCMS targets **WCAG 2.2 Level AA** for the Admin UI and the Storyblok-class visual-edit host (`@edgecms/client` `mountVisualEdit`). This is an implementation baseline and CI evidence, not a formal certification.

## Scope

| Surface | Focus | Labels | Contrast | Keyboard |
| --- | --- | --- | --- | --- |
| Admin shell | Skip link, route focus on `#content`, `:focus-visible` rings | Form/`aria-*` on core inputs; icon buttons named | Semantic tokens (`muted-foreground`, `warning`) | Sidebar, tables, dialogs (Radix), bulk actions |
| Entry live preview | Device/mode toggles focusable | `aria-label` + `aria-pressed` on chrome | Emerald/warning text tuned for AA | Mode and device groups |
| Visual-edit host | `:focus-visible` outline ≥3:1 | `aria-label="Edit {field}"`, badge `aria-hidden` | Field outline + badge use sky-700 | Tab, Enter/Space activate, Escape blurs; polite live region for save/conflict |

## Visual-edit keyboard map

1. **Tab** moves between `[data-edgecms-field]` nodes (`tabindex="0"`).
2. **Enter** / **Space** starts in-place edit (`contenteditable`, `role="textbox"`).
3. **Escape** blurs the active field (triggers the existing save/`UPDATE` path).
4. Save / conflict / error ACK messages are announced via `#edgecms-ve-live` (`aria-live="polite"`).

## Local axe gate (not required PR CI)

PR CI stays lean (typecheck / lint / unit tests / build). Run axe locally or for partner demos — fails on **critical** / **serious** violations (WCAG 2.A / 2.AA / 2.1 AA / 2.2 AA tags):

| Layer | Command | Coverage |
| --- | --- | --- |
| Visual-edit host | `bun test packages/client/src/__tests__/visual-edit-axe.test.ts` | Mounted `[data-edgecms-field]` + editing `role="textbox"` |
| Admin critical path | `bun run test:e2e:a11y` | `/sign-in`, `/admin/tenants`, collections, entries, media, users, webhooks, publishing, releases, settings |

```bash
bun run check:a11y
# or full local gate including Playwright axe + benches:
bun run check:all:full
```

Admin Playwright axe includes `color-contrast` (critical/serious) via local `check:a11y` / `test:e2e:a11y` — not a required PR Actions job. Semantic tokens (`muted-foreground`, `success`, `info`, `warning`) are the preferred palette for chrome text. Visual-edit unit axe does **not** disable contrast. Playwright Chromium install is local-only (Actions runners have flaked on unsupported OS images).

## Verification

```bash
bun run check:a11y
bun run test:client
bun run --filter edgecms-admin test src/components/skip-to-main.test.tsx
bun run --filter edgecms-admin test src/features/entries/components/related-entries-display.test.tsx
bun run lint
```

Manual: open Admin live preview + demo host, Tab through editable fields, confirm focus ring and SR announcements on save/conflict.

## Out of scope (follow-ups)

- Remaining Admin surfaces not yet in `e2e/a11y-axe.spec.ts` (entry editor, TipTap, environments, plugins, sync conflicts).
- Third-party TipTap chrome beyond existing `aria-invalid` / `aria-describedby` wiring.
- Marketing website (`apps/website`) surfaces.
