0069: The website's motion

On this page

Status: accepted. Replaces the website's part of the motion list in 0023, and departs from 0055 for the website.

Context

The website has to show what Short Leash does: an address appearing for a folder, a share's wire reaching Cloudflare, an N+1 found, a webhook's failure explained. Screenshots show a moment; a short scene shows the cause and the effect. In the app, motion follows real data or a click (0055). On the website there's no live data: a scene is a re-enactment, so it needs its own rules to stay honest and calm.

Decision

  • One signature scene per page, four on Home. Scenes use Short Leash's own vocabulary: lamps lighting, the share wire and its pulses, tiles counting up, sparklines drawing, rows arriving, a terminal typing, a pointer clicking. Sections never fade or slide in just because they scrolled into view.
  • Drawn at the final frame. A scene is real HTML of how it ends, so it reads the same with no script, to search engines and under reduced motion. Its parts say how they enter with a class and when with a delay (motion.css).
  • Plays once. Script arms a scene when motion is allowed and plays it when 40% of it is on screen. It pauses when it leaves the screen or the tab is hidden, ends on its final frame, and never loops. Replay plays it again.
  • Pause and Replay sit in every scene's top-right corner; a scene longer than 5 seconds always has Pause (WCAG 2.2.2).
  • Reduced motion: never armed, so the final frame shows; page transitions are off.
  • Interactive where it helps: the hero's folder name, framework and Share site work, Remove plays when it's pressed, and the six-place tour follows scrolling on wide screens (an IntersectionObserver picks the step crossing the middle of the window); on narrow ones its steps are tabs above the window. Scroll timelines weren't needed for that.
  • The bench behind every marketing page. The page sits on a faint dot grid, like a breadboard. Now and then a signal runs along the grid's lines, turns a corner or two and lights a lamp where it lands: amber mostly, cyan sometimes, as Short Leash's lamps are. Dots near the pointer brighten, and moving the pointer sends a signal from where it is. At most seven signals at once, drawn on one canvas at 30 frames a second, under the text at low contrast. It stops in hidden tabs, settles after 30 seconds without scrolling or pointer movement, and is off under reduced motion. The docs have none.
  • A Motion switch in the footer turns off the bench and the scenes' autoplay, so scenes show their final frames. It's remembered in this browser only.
  • Every label in a scene is the app's own string, and a scene's drawn window is hidden from screen readers behind a one-sentence summary.
  • Tech: CSS keyframes for the parts, and Motion (motion, already in the app) for inView and counting numbers. Cross-document view transitions on marketing pages only, where the browser supports them. No WebGL, Lottie, Rive or client-side router.
  • Budgets on marketing pages: at most 15 KB of script on first load and 45 KB with every scene's script, and 35 KB of CSS, gzipped; checked from the build.

Consequences

  • Pages explain features without video, stay sharp in Light and Dark, and follow the app's look through the same tokens.
  • A scene is a drawing of the app, so it can fall behind it; src/scenes/README.md lists the screen each one copies.
  • Motion stays bounded: a new kind of website motion needs a reason of this kind and a line in CLAUDE.md.