Skip to content

fix(website): remediate WCAG accessibility issues and add axe regression guardrail#2180

Open
IEvangelist wants to merge 2 commits into
github:mainfrom
IEvangelist:ievangelist-dapine-accessibility-fixes
Open

fix(website): remediate WCAG accessibility issues and add axe regression guardrail#2180
IEvangelist wants to merge 2 commits into
github:mainfrom
IEvangelist:ievangelist-dapine-accessibility-fixes

Conversation

@IEvangelist

Copy link
Copy Markdown

What & why

A full axe-core accessibility sweep of every website page — in both light and dark themes — surfaced several WCAG violations (1.3.1, 4.1.2, 1.4.3). This PR fixes them at the source and adds a checked-in regression guardrail so they can't creep back in.

All fixes were verified against the production build (astro preview + axe-core), not just dev, and the audit is now green across all 12 routes × 2 themes.

Accessibility fixes

Rule WCAG Fix
aria-allowed-role 1.3.1 / 4.1.2 The shared resource card rendered an <article> with role="listitem", which isn't an allowed role for that element (e.g. #arcade-canvas on /extensions/). Changed the wrapper to <div role="listitem"> so the role is valid. Fixes it for every card site-wide.
aria-required-children 1.3.1 Removed role="list" from the tools, contributors, and cookbook containers whose direct children aren't list items.
nested-interactive 4.1.2 Removed tabIndex=0 from extension cards and rendered the author as a non-interactive <span> so no interactive control is nested inside another. The author link is still available in the details modal.
color-contrast 1.4.3 .btn-primary now has explicit white text with an AA-compliant hover (#7326d6, 7.05:1). Bumped the dark-theme secondary-text gray --sl-color-gray-3#84849c (5.32:1) so ToC / meta / footer text passes AA.

Regression guardrail

  • website/scripts/a11y-audit.mjs — runs axe-core over every route in both themes against the production build. It fails the build on critical/serious violations only; moderate/minor findings are reported but non-blocking.
  • Important detail: the audit disables CSS transitions/animations before sampling colors. Theme switches animate background/text over ~0.2s, and running axe mid-transition produces false-positive contrast failures (a dark card background momentarily bleeding through a light page). Disabling transitions makes axe measure the settled, steady-state colors users actually see.
  • Added npm scripts: website:a11y (root, builds then audits) and a11y (in website/), plus a short Accessibility section in website/README.md.

⚠️ One follow-up needed: CI wiring

The audit is meant to run in the Build Website workflow, but that change was omitted from this PR because my authoring token lacks the workflow OAuth scope and GitHub rejects pushes that touch .github/workflows/. Please add this step to .github/workflows/build-website.yml (right after the Build Astro site step):

      - name: Accessibility audit
        run: |
          npx playwright install --with-deps chromium
          npm run a11y
        working-directory: ./website

Verification

  • npm run a11y0 blocking violations, 0 non-blocking across all 12 routes × 2 themes.
  • Manually spot-checked both themes at steady state (extensions, cookbook, doc pages) — no mixed light/dark artifacts, all text passes AA.

Co-authored-by: Copilot App 223556219+Copilot@users.noreply.github.com

…ion guardrail

Fixes accessibility violations found by an axe-core sweep of every website
page in both light and dark themes:

- aria-allowed-role (WCAG 1.3.1, 4.1.2): the shared resource card rendered
  an <article> with role="listitem", which is not an allowed role for that
  element. Switched the wrapper to a <div role="listitem"> so the listitem
  role is valid (affected every card, e.g. #arcade-canvas on /extensions/).
- aria-required-children (WCAG 1.3.1): removed role="list" from the tools,
  contributors, and cookbook containers whose children are not list items.
- nested-interactive (WCAG 4.1.2): removed tabIndex=0 from extension cards
  and rendered the author as a non-interactive span so no interactive
  control is nested inside another (the author link remains in the modal).
- color-contrast (WCAG 1.4.3): gave .btn-primary explicit white text with an
  AA-compliant hover (#7326d6), and bumped the dark-theme secondary text gray
  (--sl-color-gray-3) to #84849c (5.32:1) so ToC / meta / footer text passes.

Adds a checked-in regression guardrail:

- website/scripts/a11y-audit.mjs runs axe-core over all routes in both themes
  against the production build and fails on critical/serious violations only
  (moderate/minor are reported but non-blocking). Transitions/animations are
  disabled before sampling so axe measures settled, steady-state colors
  instead of mid-theme-transition frames.
- Adds npm scripts (website:a11y at the root, a11y in website/) and README
  docs. The matching Build Website CI step is proposed in the PR description
  (omitted from this commit because the authoring token lacks workflow scope).

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 1, 2026 15:23
@IEvangelist IEvangelist requested a review from aaronpowell as a code owner July 1, 2026 15:23
@github-actions github-actions Bot added new-submission PR adds at least one new contribution website-update PR touches website content or code labels Jul 1, 2026
@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

🔴 Contributor Reputation Check: HIGH risk

Check Risk
Profile HIGH
Credential audit NONE

Maintainers: please review this contributor before merging.
See the workflow run for full details.
Automated check powered by AGT.

@github-actions github-actions Bot added the needs-review:HIGH Contributor reputation check flagged HIGH risk label Jul 1, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Remediates WCAG/axe accessibility findings across the website (roles, nested interactive elements, and color contrast) and introduces a Playwright + axe-core production-build audit script intended to prevent regressions.

Changes:

  • Fixes multiple ARIA semantics issues across cards and listing containers (role validity, required children, nested interactive controls).
  • Adjusts global/starlight theme colors to meet WCAG AA contrast requirements.
  • Adds a checked-in accessibility audit script (website/scripts/a11y-audit.mjs), plus npm scripts and README guidance for running it.

Reviewed changes

Copilot reviewed 11 out of 12 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
website/src/styles/starlight-overrides.css Raises dark-theme secondary gray to improve AA contrast.
website/src/styles/global.css Forces .btn-primary text to white and sets an AA-compliant hover color.
website/src/scripts/pages/extensions-render.ts Removes focusability on extension cards and renders author as non-interactive text to avoid nested interactive issues.
website/src/scripts/pages/card-render.ts Switches card wrapper from <article> to <div> to allow role="listitem" without aria-allowed-role violations.
website/src/pages/tools.astro Removes invalid role="list" from tools container.
website/src/pages/learning-hub/cookbook/index.astro Removes invalid role="list" from cookbook results container.
website/src/pages/contributors.astro Removes invalid role="list" from contributors container.
website/scripts/a11y-audit.mjs Adds production-preview accessibility audit over 12 routes × 2 themes, gating on serious/critical only.
website/README.md Documents how to run the audit and summarizes authoring conventions related to a11y.
website/package.json Adds a11y script and devDependencies for axe-core and playwright.
website/package-lock.json Locks new devDependencies (axe-core, playwright).
package.json Adds root website:a11y script to build then audit.
Files not reviewed (1)
  • website/package-lock.json: Generated file

Comment thread website/scripts/a11y-audit.mjs Outdated
Comment thread website/scripts/a11y-audit.mjs
- Fail fast when a route navigation returns a non-2xx response, so the
  guardrail can't silently pass against a broken/missing route (page.goto
  resolves even for 4xx/5xx).
- Launch the Astro preview server via `node <astro-bin>` instead of
  `spawn(..., { shell: true })`. Removing the shell layer keeps signal
  delivery / detached-PGID shutdown predictable; resolving Astro's bin and
  running it with process.execPath also avoids the EINVAL that modern Node
  raises when spawning the npx.cmd shim without a shell on Windows.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-review:HIGH Contributor reputation check flagged HIGH risk new-submission PR adds at least one new contribution website-update PR touches website content or code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants