docs-site: hero constellation, entrance and scroll motion with accessibility guardrails - #36
Merged
Merged
Conversation
…tlas animation) Phase 1, CSS motion: - PageHeader entrance: eyebrow, title, lead, meta, actions and figure ease in with a 60 ms stagger, CSS only, under prefers-reduced-motion: no-preference. - data-reveal: rise-into-place on scroll via CSS scroll-driven animations (animation-timeline: view() behind @supports). Moves without fading so text contrast is identical at every scroll position. - data-lift: hover lift with shadow on pointer devices only. - assets/repository-atlas-journey.svg: declarative entrance animation in an SVG <style> block (hub, cards, links, then journey lines drawing in with arrowheads fading in after them). Markers replaced by explicit arrowhead paths. Everything behind prefers-reduced-motion: no-preference; no script. Phase 2, constellation hero background: - Vanilla canvas engine (seeded PRNG, node clamp, distance-faded edges, pulses) and renderer, lazy-loaded after idle into a PageHeader backdrop slot on Home only. Code-split chunk about 3 KB gzipped. - Pauses off-screen, when the tab is hidden, and on a visible "Pause background" / "Play background" button with aria-pressed (WCAG 2.2.2). Static single frame under reduced motion with opt-in play. - Canvas is aria-hidden, absolutely positioned, zero layout shift. Copy column dims the drawing to 25 percent to protect text contrast. Phase 3, guardrails: - tests/browser/motion.spec.ts: running/paused/static states, pause control size and toggling, off-screen pause, CLS < 0.02, no keyframe animation under reduced motion, chunk budget and main-bundle exclusion, entrance settling, reveal never fading, Atlas SVG free of scripts and inert under reduced motion. - a11y.spec.ts waits for time-based animations to settle before running axe. - 16 unit tests for the engine, renderer and component. - README: hero background animation and other motion sections. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds motion to the GitHub Pages site (
docs-site/) in the spirit of the animated hero on sample-ac-central, built to the constraints this site already follows: no runtime network requests, no external assets, no analytics, WCAG 2.2 AA, zero layout shift. Every effect respectsprefers-reduced-motion, the only auto-playing effect has a pause control (WCAG 2.2.2), and a new Playwright spec keeps those promises enforced in CI.Repository-side change is one file:
assets/repository-atlas-journey.svggains a declarative CSS entrance animation. No project folder changed.What changed
Phase 1: CSS motion
PageHeader: eyebrow, title, lead, meta, actions and figure ease in with a 60 ms stagger, CSS only, underprefers-reduced-motion: no-preference.animation-timeline: view()behind@supports), exposed as adata-revealattribute. Blocks rise into place but never fade, so text contrast is identical at every scroll position and axe or Lighthouse see the same colours as the reader. Browsers without support show content at rest.data-lifton cards and tiles, only on pointer devices (hover: hover).<style>block inside the SVG so it also runs inside<img>, and it sits entirely behindprefers-reduced-motion: no-preference. Markers were replaced by explicit arrowhead paths so they can fade in after their line.Phase 2: constellation canvas hero background
React.lazyafter the page is idle, code-split into its own chunk with a gzip budget enforced by test.aria-pressed. Capped at 30 fps and sized withdevicePixelRatioclamped.aria-hidden, positioned absolutely behind the header, and never affects layout (CLS measured 0).Phase 3: guardrails
tests/browser/motion.spec.ts: running state, pause control size and toggling, off-screen pausing, CLS under 0.02, static frame under reduced motion with zero running keyframe animations, chunk size budget and main-bundle exclusion, hero entrance settling, scroll reveal never fading and settling in view, Atlas SVG free of scripts and inert under reduced motion.tests/browser/a11y.spec.tsnow waits for time-based animations to finish before running axe, so it audits the settled page rather than a frame of the hero mid-entrance.validate_static.py, audit, full browser suite with axe.Verification
npm run typecheck,npm run lint(zero warnings),npm test(917 tests),npm run build(37 pages prerendered),npm run validate:static,npm run audit(0 vulnerabilities),npm run test:browser(167 passed, 2 viewport-conditional skips, 0 failed) on Node 22 locally.Notes
reducedMotionemulation does not propagate into SVG documents embedded via<img>, so the SVG test loads the file directly. With the browser-level preference (--force-prefers-reduced-motion) the embedded image renders static, which is what real users get.animation-timelinesupport see content at rest; the reveal is progressive enhancement only.🤖 Generated with Claude Code