docs(website): theme a11y/contrast and git-dated sitemap lastmod (#590 P3s) - #614
Conversation
…link, skip link, home <main>, contrast tokens (#590) Theme-level fixes for the P3 "theme a11y / contrast" audit items, measured at 1440×900 on Rspress 2.0.21 defaults. Only website/theme/index.tsx and website/styles/index.css change. - SwitchAppearance: re-exported as div[role=button] with tabIndex, a translated aria-label, aria-pressed (set after mount to avoid a hydration mismatch) and Enter/Space handling. Kept a div because NavHamburger mounts it inside its own <button>. Brand focus ring declared in CSS. - SocialLinks: wrapper sets aria-label (hostname) on icon-only anchors. - Skip link in the `top` slot targeting a zero-size #ab-content marker in `beforeDocContent` and in the custom HomeLayout; hidden on 404/custom/blank. - HomeLayout: hero + features wrapped in <main> (Markdown render for llms.txt keeps the default). Hero title stays a div; an <h1> would need a HomeHero fork. - --rp-c-text-3: 1.85:1 → 5.18:1 light, 3.19:1 → 5.37:1 dark (prev/next labels, home footer, last-updated). - --rp-c-brand light: #0d8f80 3.99:1 → #0b8072 4.83:1 (same hue/saturation). - Shiki light string #31a94d 3.04:1 → #26843c 4.72:1; light comment 2.06:1 → 4.74:1, light parameter 2.30:1 → 4.66:1, dark comment 3.84:1 → 5.02:1.
…ns after the file exists (#590)
|
commit: |
…main> + skip target, string/tertiary tokens pass on highlighted and hover backgrounds, sitemap lastmod asserted post-build
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
# Conflicts: # website/docs/en/reference/targets-artifacts.mdx # website/docs/zh/reference/targets-artifacts.mdx
Third PR for #590 (after #599 and #610): the two remaining P3s the audit measured that were worth doing rather than deferring — theme accessibility/contrast and sitemap
lastmod. Website (private package) and the docs workflow only, soskip-changeset.Theme a11y and contrast (
website/theme/index.tsx,website/styles/index.css)Audit findings at 1440×900 on Rspress 2.0.21 defaults, and what changed:
divwith no role/name, not focusableSwitchAppearancereplaces the default site-wide (Nav,NavScreen,NavHamburgerimport it from@rspress/core/theme):role="button",tabIndex=0, translatedaria-label,aria-pressedafter mount (hydration-safe), Enter/Space toggle, brand focus ring. Stays adivbecauseNavHamburgermounts it inside its own<button>.SocialLinkswrapper setsaria-labelfrom the link's host (github.com) on icon-only anchors.topslot renders "Skip to main content" / "跳至主要内容" as the first focusable element, targeting a zero-size#ab-contentmarker placed bybeforeDocContent(doc pages) and the customHomeLayout; hidden on 404/custom/blank pages.<main>/<h1>HomeLayoutwraps hero + features in<main>(footer stays outside to keepcontentinfo). The hero title stays adiv: an<h1>would need aHomeHerofork.--rp-c-text-3)#0d8f803.99:1#0b80724.83:1 — same hue and saturation, lightness 31 % → 27 %;theme-colormeta follows#31a94d3.04:1#26843c4.72:1; the light comment (2.06:1 → 4.74:1), light parameter (2.30:1 → 4.66:1) and dark comment (3.84:1 → 5.02:1) tokens failed the same way and were fixed alongsideEvery ratio is WCAG 2.x, computed from the declared colours over the theme backgrounds; the values are in the CSS comments next to each token.
Sitemap
lastmod(website/plugins/sitemap-lastmod.ts,.github/workflows/docs.yml)@rspress/plugin-sitemapdates every<url>with the source file's mtime — in CI that is checkout time for authored pages and build time for generated ones, so every deploy told crawlers every page had changed, and the plugin has no option to turn it off.sitemapLastmodwrapspluginSitemap(Rspress runsafterBuildhooks in parallel, so a second plugin cannot order itself after the write) and rewrites<lastmod>to the last commit touching the page's source: the.mdx/.mdfor authored pages,packages/agent-bundle/srcfor/api/**,src/adapters/capabilitiesfor hosts/events/notices,docs/diagnostics.mdfor the diagnostics page. On a shallow clone or when git is unavailable the element is omitted rather than wrong.docs.ymlchecks out full history bloblessly (fetch-depth: 0,filter: blob:none: commits and trees only, which is allgit log -- <path>needs; the pack is 159 MiB with blobs).Local gate (
pnpm docs:site:build) green; sitemap has 1,948 URLs with dates ranging from 2026-09-03 to today per page.Self-review
Reviewer:
gpt-5.6-sol-medium(implementing lanes:claude-fable-5-1-thinking-maxfor the theme,gpt-5.6-sol-mediumfor the first sitemap draft,claude-fable-5-1-thinking-maxfor the plugin composition, CI change and integration). Two independent Sol runs on the pre-fix diff (ad0e259):role="button"switch also renders insideNavHamburger's<button>(shown at 769–1280 px). Fixed (9d0d846): after mount the switch detectsclosest('button')and renders as the default theme's plain click target there; the standalone copy keeps role/name/tab stop. Verified headless: at 1024 px the nested copy has no role/tabindex after hydration, at 1440 px Tab reaches the switch and Enter toggles the theme.<main>and no skip target. Fixed:NotFoundLayoutwraps the default in<main>with the skip target;404.htmlnow has landmark, target and link.{n}/[!code highlight]background). Fixed:#227a37— 5.37:1 on white, 4.78:1 highlighted.opacity: .7on the hovered card dropped the label to ~2.8:1, and the dark token was 4.11:1 on the mute background. Fixed: hover keeps full opacity (the background change remains as feedback); dark--rp-c-text-3at 65 % → 7.08:1 / 5.08:1.sitemap-lastmod.ts. Dismissed as a unit test, addressed as a gate assertion: the unit pool ispackages/**/tests/**/*.test.tsandwebsite/has no harness (none of its plugins or scripts are unit-tested);check-built-links.mjsnow asserts every<lastmod>parses, is not in the future, and that the values are not all identical when there are more than ten URLs — the exact regression this change removes — and was verified to fail on a doctored sitemap.No findings on hydration (
aria-pressedafter mount), override reachability, skip targets on doc/API pages, desktop width rules, sitemap route mapping, blobless history, or the checkout assumptions of other steps. Second pass after the fixes: one residual, dismissed: at 769–1280 px the visible switch is the copy insideNavHamburger's<button>, which now renders without a role or tab stop, and the hamburger's own Enter/Space only opens the menu — so a keyboard user at those widths still cannot toggle appearance. That is the default theme's behaviour at those widths (the switch was a click-onlydivthere before and after this PR), the fix is a fork ofNavHamburgerthat renders its popover outside the trigger, and the site's acceptance viewport is 1440 × 900 desktop (AGENTS.md). Recorded on #590 as deferred / upstream-worthy. All contrast ratios were recomputed independently (5.37, 4.79, 7.10, 5.09 before 8-bit rounding); the sitemap assertion's one theoretical false positive (a single commit touching all 75 authored sources with no other history) was judged acceptable for this site.Deslop
cursor-grok-4.6-high-fast, 8 edits — ran after this PR had merged (the owner's rule arrived at 08:39), so the comment trims land in #622; no behaviour change.Refs #590.