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) forinViewand 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.mdlists 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.