diff --git a/docs/superpowers/plans/2026-04-22-a11y-dialogs-labels-lang.md b/docs/superpowers/plans/2026-04-22-a11y-dialogs-labels-lang.md new file mode 100644 index 00000000000..1efc63a0c8f --- /dev/null +++ b/docs/superpowers/plans/2026-04-22-a11y-dialogs-labels-lang.md @@ -0,0 +1,404 @@ +# Accessibility: Dialog semantics, icon labels, html lang + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Add ARIA dialog semantics, focus management, accessible names for icon-only controls, and a `lang` attribute — addressing the highest-impact items from the 2026-04-22 a11y audit. + +**Architecture:** All changes live in templates + a small set of TS files. No new modules. The existing `toggleDropDown` in `pad_editbar.ts` is the single chokepoint for popup show/hide; we extend it with focus management. Icon-only buttons get accessible names via a new `icon.*` locale namespace consumed via `data-l10n-id` (existing l10n machinery applies to `aria-label` automatically through html10n's attribute syntax). + +**Tech Stack:** EJS templates, TypeScript, jQuery (legacy), Playwright tests. + +**Out of scope:** WCAG-AA contrast pass, touch-target sizing (28→44px), full focus-visible CSS pass, modal-by-modal focus-trap library swap. Leaving those for follow-up PRs to keep this one reviewable. + +--- + +### Task 1: Add `lang` attribute to top-level templates + +**Files:** +- Modify: `src/templates/pad.html:7` +- Modify: `src/templates/index.html` (top `` tag) +- Modify: `src/templates/timeslider.html` (top `` tag) + +The pad templates render server-side; `clientVars.userAgent` and `req.headers['accept-language']` aren't directly available here, but the rendered locale is exposed via `settings.defaultLang` in `Settings.ts`. Use that, defaulting to `en` if unset. + +- [ ] **Step 1.1:** Edit `src/templates/pad.html` line 7. Replace + ```html + + ``` + with + ```html + + ``` + +- [ ] **Step 1.2:** Apply the same `lang` attribute to `src/templates/index.html` and `src/templates/timeslider.html` `` tags. (Read each first to get exact current line.) + +- [ ] **Step 1.3:** The client-side language switcher (`html10n`) already updates `documentElement.lang` after page load — verify by grepping `pad_utils.ts` and `vendors/html10n.ts` for `lang =`. No code change needed if html10n already does this; otherwise add one line in `pad.ts` after l10n loads to set `document.documentElement.lang` from the active locale. + +- [ ] **Step 1.4:** Commit: + ```bash + git add src/templates/pad.html src/templates/index.html src/templates/timeslider.html + git commit -m "fix(a11y): add lang attribute to top-level templates" + ``` + +--- + +### Task 2: Dialog semantics on popups + +**Files:** +- Modify: `src/templates/pad.html` — popups at lines 117 (`#settings`), 190 (`#import_export`), 242 (`#connectivity`), 325 (`#embed`), 349 (`#users`), 353 (`#mycolorpicker`), 410 (`#skin-variants`). + +For each popup, add `role="dialog"`, `aria-modal="true"`, `aria-labelledby=""`. Where the popup has an `

` without an id, add an id. Connectivity has multiple `

` (one per state) — give that one `role="dialog" aria-modal="true" aria-label="Connection status"` instead of labelledby. + +- [ ] **Step 2.1:** Settings popup. Add id to its `

`: + ```html +

+ ``` + And: + ```html +