Skip to content

ci(docs): add axe accessibility checks and fix existing violations - #1048

Merged
bensabic merged 10 commits into
mainfrom
ci/docs-a11y
Oct 27, 2026
Merged

bensabic merged 10 commits into
mainfrom
ci/docs-a11y

Conversation

@roboeve

@roboeve roboeve Bot commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Adds a docs-a11y CI job that builds the docs site, serves it locally, and runs axe-core against every page. It also fixes all of the violations the job found on the current site.

  • apps/docs/scripts/a11y.mts reads page URLs from /sitemap.md and adds /, /adapters, and /resources, which the sitemap does not list. It checks each page in light and dark mode with @axe-core/playwright against the WCAG 2.0, 2.1, and 2.2 A and AA rules.
  • New docs pages are picked up automatically through the sitemap.
  • Run it locally with pnpm --filter docs a11y [base-url]. The base URL defaults to http://localhost:3000.

Fixes

The first run against chat-sdk.dev failed all 192 page checks across 7 rules. This PR fixes all of them:

Rule Where Fix
link-name Every page The navbar home links wrap the Chat SDK logo, whose SVG is aria-hidden. Logo in geistdocs.tsx now includes visually hidden "Chat SDK" text.
color-contrast About half of page checks Light-mode --color-fd-muted-foreground moves from Geist gray-800 to gray-900. Home page code uses github-light-default instead of github-light, whose orange token was 3.5:1. Adapter notice boxes use text-gray-900.
button-name / The home page copy button has an aria-label.
target-size / Removed the negative margin that made the last example group dot overlap its neighbor.
scrollable-region-focusable /, adapter pages, /docs/api/*, /docs/testing Home page code windows are focusable. MDX tables and TypeTables render inside a focusable, labeled region that handles horizontal scrolling, wrapping the Geistdocs table.
aria-valid-attr-value /adapters The filter tabs pointed aria-controls at Radix panels that are never rendered. They now point at the adapter results list.
label /docs/contributing/documenting GFM task list items wrap their content in a label.

Known violations

KNOWN_VIOLATIONS in the script accepts violations that come from a dependency and cannot be fixed here right away. Entries print as warnings instead of failing the job, and the script reports entries that stop matching.

It has one entry. Since @vercel/geistdocs 2.13, the sidebar section header button shows the section name (for example "Official Adapters") but has the aria-label "Back to all documentation sections". axe flags this as label-content-name-mismatch on every adapter page. The entry uses "*" because the affected pages grow with the adapter catalog, and should be removed once Geistdocs fixes the label.

Test plan

  • Ran the script against https://chat-sdk.dev to find the original violations, and sampled every page in light mode to list each failing color pair.
  • Checked that every github-light-default token color is at least 4.5:1 on white.
  • pnpm check, tsc for apps/docs, pnpm knip, and pnpm install --frozen-lockfile pass.
  • The docs-a11y job runs on this PR against a local production build of the docs site.

Checklist

  • All commits are signed and verified
  • All commits are signed off for the DCO (git commit -s)
  • pnpm validate passes
  • Changeset added (or N/A — see CONTRIBUTING.md): N/A, docs site and CI only
  • Documentation updated (or N/A): N/A

Adds a docs-a11y job that builds apps/docs, serves it, and runs axe-core against every page in the sitemap in light and dark mode. Existing violations are listed in KNOWN_VIOLATIONS so the job only fails on new ones.
@vercel

vercel Bot commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
chat Ready Ready Preview, v0 Oct 27, 2026 12:45pm UTC

@socket-security

socket-security Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addednpm/​@​axe-core/​playwright@​4.14.01001001009870
Addednpm/​playwright@​1.64.11001001009980

View full report

Fixes the logo link name, light-mode muted text and home page code contrast, the home copy button name, example tab target size, scrollable code regions, adapter filter tab aria-controls, and GFM task list checkbox labels. Removes those entries from KNOWN_VIOLATIONS; wide MDX tables remain because the wrapper comes from @vercel/geistdocs.
@roboeve roboeve Bot changed the title ci: run axe-core accessibility checks on the docs site ci(docs): add axe accessibility checks and fix existing violations Oct 13, 2026
Wraps the Geistdocs table in a focusable, labeled region that owns horizontal scrolling, so keyboard users can scroll wide tables. Clears the last KNOWN_VIOLATIONS entry.
@roboeve

roboeve Bot commented Oct 19, 2026

Copy link
Copy Markdown
Contributor Author

docs-a11y failed on 117e8d6 because main moved to @vercel/geistdocs 2.11.0, where TypeTable renders the Geistdocs table internally and skips the table override. That left scrollable-region-focusable on 13 pages with prop tables (Discord, Slack, Telegram, /docs/api/chat, and others).

588da04 wraps TypeTable in the same focusable scroll region as MDX tables. Against a local production build of this branch merged with current main, all 198 of 198 checks pass. tsc and pnpm check pass too. CI on the new head is still running.

roboeve Bot added 2 commits October 27, 2026 11:59
Rebuild the lockfile from main's pnpm-lock.yaml plus this PR's docs devDependencies (@axe-core/playwright, playwright) so main merges into this branch without a lockfile conflict.
@bensabic
bensabic marked this pull request as ready for review October 27, 2026 12:01
@bensabic
bensabic requested a review from a team October 27, 2026 12:01
@roboeve

roboeve Bot commented Oct 27, 2026

Copy link
Copy Markdown
Contributor Author

docs-a11y failed on cf56ce7 after the main merge brought in @vercel/geistdocs 2.13.2. All 96 failing checks are one rule, label-content-name-mismatch, on one element: the Geistdocs sidebar section header button, which shows the section name ("Official Adapters") but has aria-label="Back to all documentation sections". It renders on every adapter page, and the button is internal to Geistdocs, so it can't be fixed here.

2c702ff adds it to KNOWN_VIOLATIONS with "*" and a comment, so it reports as a warning until Geistdocs fixes the label. I reproduced the 96 failures against a local production build of cf56ce7. With the entry, all adapter pages and the first 120 of 198 checks passed before I stopped waiting on the local run. tsc and pnpm check pass. CI on the new head is still pending. I also updated the PR description to cover this and the earlier TypeTable fix.

Signed-off-by: Ben Sabic <bensabic@users.noreply.github.com>
@bensabic
bensabic merged commit 92390a4 into main Oct 27, 2026
27 checks passed
@bensabic
bensabic deleted the ci/docs-a11y branch October 27, 2026 14:28

This branch was successfully deployed

1 active deployment
Preview — 3df69c15 Deployed Oct 27, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant