Back to Langflow

IBM Level 1 PR Accessibility Remediation

.agents/skills/ibm-a11y-pr-remediation/SKILL.md

1.12.0.dev07.3 KB
Original Source

IBM Level 1 PR Accessibility Remediation

Scope is IBM Equal Access Level 1 only. Default mode is fix, not report-only. Scan every frontend surface touched by the PR/branch and remediate all in-scope issues until both engines are green (or only documented baselines remain).

This skill is a PR-scoped orchestrator. It does not duplicate detailed engine/pattern guidance — read the linked skills for that:

  • ibm-a11y-testing-guide — which engine/test layer to use, POUR checklist, axe-vs-IBM gaps, Radix/AG-Grid gotchas, baselines.
  • ibm-a11y-route-scan — Python scanner options for ad-hoc route batches.
  • ibm-a11y-level1-audit — Level 1 criteria references and report template, useful when the user wants a formal audit report for the PR instead of (or in addition to) fixes.
  • frontend-i18n — accessible names / UI strings must go through i18n.

Mandate

  1. Diff the PR (or current branch vs its merge base) for src/frontend/** changes.
  2. Map changed files → UI surfaces → routes / components / states to scan.
  3. Run both axe (Jest where applicable) and IBM Equal Access (Playwright page.runA11yScan and/or scripts/a11y/a11y_scan.py — see ibm-a11y-testing-guide / ibm-a11y-route-scan).
  4. Fix every in-scope Level 1 violation in the changed surfaces. Do not stop at a findings list unless the user says report only (in that case, hand off to ibm-a11y-level1-audit).
  5. Re-scan until assert mode passes. Add/update a11y specs when coverage is missing.
  6. Report what changed, commands run, and any baselined/deferred debt.

Do not invent new tag names, silently disable scans, or expand into IBM Level 2/3 unless asked.

Progress checklist

IBM L1 PR A11y:
- [ ] 1. Collect changed frontend files
- [ ] 2. Map files → surfaces / routes / states
- [ ] 3. Scan (IBM + axe)
- [ ] 4. Fix all in-scope violations
- [ ] 5. Add/update tests if needed
- [ ] 6. Re-scan assert-green
- [ ] 7. Report back

1. Collect changed frontend files

Prefer the PR merge base when a PR exists; otherwise the branch merge base vs main/master.

bash
# PR number known
gh pr diff <n> --name-only | grep -E '^src/frontend/' || true

# Current branch vs upstream default
BASE=$(git merge-base HEAD origin/main 2>/dev/null || git merge-base HEAD origin/master)
git diff --name-only "$BASE"...HEAD -- 'src/frontend/**'

# Include uncommitted work when the user is mid-change
git diff --name-only HEAD -- 'src/frontend/**'
git diff --name-only --cached -- 'src/frontend/**'
git ls-files --others --exclude-standard 'src/frontend/**'

Include:

  • src/frontend/src/**/*.{tsx,ts,jsx,js,css} (UI)
  • src/frontend/tests/a11y/** (existing coverage)
  • Locale files only when they change accessible names / labels

Skip pure non-UI churn unless it affects a11y (e.g. test helpers that change focus / ARIA). If no frontend files changed, say so and stop.

2. Map files → surfaces

For each changed file, identify:

Change typeScan target
Page / routeThat route + meaningful states (empty/populated/modal/mobile)
Shared component (TableComponent, dialogs, menus)Every consumer page that uses it — not only the file you touched
PrimitiveJest axe on the primitive + any Playwright surface that embeds it
Spec / baseline onlyRe-run that spec; no product fix unless it fails
a11y_routes.jsonUpdate static coverage; run static or route scan

List interactive controls and states (default, empty, populated, open modal / menu, selected row, error, mobile). Prefer existing specs under src/frontend/tests/a11y/.

3. Scan (both engines must pass)

Automated a11y is not one tool — see ibm-a11y-testing-guide for the full engine comparison and gotchas. Summary:

  • axe-core — Jest axe() (@/utils/a11y-test), jsdom-only.
  • IBM Equal Access — stricter on ARIA structure and keyboard semantics. Playwright page.runA11yScan(label) for stateful surfaces (modals/menus/selected/editing); scripts/a11y/a11y_scan.py for default-loaded page only.
bash
cd src/frontend
RUN_A11Y=true RUN_A11Y_ASSERT=true npx playwright test tests/a11y/<feature>.a11y.spec.ts --project=chromium --workers=5

# Python scanner playwright deps are NOT in default uv sync.
# One-time: uv run --with playwright playwright install chromium
uv run --with playwright python scripts/a11y/a11y_scan.py \
  --url http://localhost:3000 \
  --routes /settings/<route> \
  --out /tmp/a11y.json --markdown /tmp/a11y.md --timeout-ms 45000

RUN_A11Y=true runs the scan; RUN_A11Y_ASSERT=true fails on new violations. After changing a shared component, re-scan every page that uses it.

For component-only changes:

bash
cd src/frontend
npx jest path/to/<name>.a11y.test.tsx --runInBand

Do not invent findings — prefer scanner output plus manual Level 1 spot checks scanners miss (keyboard trap both ways, focus restore, 320px reflow, color-not-only).

4. Fix all in-scope Level 1 violations

Default: fix. Only list proposed fixes without editing if the user asked report only — then hand off to ibm-a11y-level1-audit for the formal report format.

Rules:

  • Prefer semantic HTML over ARIA.
  • Follow the Langflow patterns in ibm-a11y-testing-guide (AG Grid, Radix asChild, focus restore, icon-only aria-label).
  • Route new UI strings / aria-labels through i18n (t(...), all locale files) per frontend-i18n.
  • Keep fixes minimal; do not refactor unrelated UI.
  • Do not silently disable scans. Use IBM baselines under src/frontend/tests/a11y/baselines/ only for documented framework debt.
  • Map each issue to a Level 1 WCAG/IBM id; defer anything listed as Level 2/3 in the criteria guide (ibm-a11y-level1-audit/references/ibm-level1-criteria.md) unless the user expands scope.

Manual Level 1 spot checks (when relevant)

  • 2.1.1 / 2.1.2: Tab and Shift+Tab; Escape closes overlays; no trap.
  • 2.4.3 / 2.4.7: Focus order matches visual order; focus ring visible.
  • 1.4.10: 320px / ~400% zoom — no essential horizontal scroll.
  • 1.4.1: Status/errors not color-only.
  • 3.3.1 / 3.3.2: Errors in text and tied to fields; inputs labeled.

5. Tests / coverage

SurfaceSpec
Static routesstatic-routes.a11y.spec.ts (+ scripts/a11y/a11y_routes.json)
Authauth-pages.a11y.spec.ts
Core pagescore-pages.a11y.spec.ts
Data-richfiles.a11y.spec.ts, api-keys.a11y.spec.ts, global-variables.a11y.spec.ts
Other data-richdata-rich-routes.a11y.spec.ts

If you fixed a state with no scan, add one (and keyboard tests for custom keyboard behavior) following files.a11y.spec.ts / api-keys.a11y.spec.ts patterns.

Tag every Playwright a11y test @release plus a domain tag (@workspace / @api / @database / @components / @starter-projects). Import test/expect from ../fixtures.

6. Re-scan and report

Re-run the same scans with RUN_A11Y_ASSERT=true. Each finding → fixed | baselined | open.

When done, state:

  • Changed frontend files considered
  • Surfaces / states scanned
  • Fixes applied (files + what)
  • Commands run — whether both axe and IBM ran and both reported zero
  • Specs / baselines added or updated
  • States skipped and why
  • Remaining risk or accepted limitation