Space Works motion kit
Part of Design System v2.0. Values are copied from the app as shipped in SpaceWorks 0.12.0.
Every animation in the product as a reusable, framework-free template: one folder per family, each with the CSS
(copied unchanged from the app, using the tokens in ../tokens/tokens.css), react/ copies
of the real app files, a standalone demo.html (light and dark, honours reduced motion), animated previews/
(WebP and GIF) and a README that says what it is, where the app uses it, why, the timing and easing tokens, the
trigger, reduced-motion and dark behaviour, do and don’t, and copy-paste usage.
The full catalogue with every trigger and reduced-motion note is ../docs/motion.md. The
rules behind it: transform and opacity only, enter decelerates and exit accelerates, nothing on an interaction path
over 240 ms, hover is colour only, reduced motion is a floor, never loop outside a loader, check both themes.
Folders
Section titled “Folders”| Folder | What it covers |
|---|---|
box-open/ |
The box loader (loop), the inline spinner, the in-button mono spinner, the logo hover and focus opening, the cold-start splash opening |
theme-reveal/ |
The light/dark switch: a circle growing from the toggle |
search/ |
The shared animated search field |
route-transition/ |
Page change: old out, new in, only the main region |
page-enter/ |
List stagger, sign-in facets and showcase, areas panel and proof |
scroll-reveal/ |
Landing story: pinned hero, handover steps beside a sticky record, reveal on scroll |
overlays/ |
Scrim fade, dialog pop, phone sheet, side drawers, menus and popovers |
toast/ |
Status toast in and out |
sidebar/ |
Sliding section and tab indicator |
collapse/ |
Height collapse via grid rows, disclosure chevrons |
skeleton/ |
Still loading placeholders and the progress width |
hover-press/ |
Colour-only hover, press sink, card, row and link hover |
feedback/ |
Verify stamp, result arrive, pass tear, logbook, return confetti |
delight/ |
Logo flap spring and pop, Patch, companion walk, glyph tilt, card tilt and flip |
kiosk-display/ |
Display slide fade and the kiosk and TV token override |
Every animation, where it lives
Section titled “Every animation, where it lives”| Animation | Folder | Where | Why |
|---|---|---|---|
| Mark opening on hover and focus | box-open/ |
Every Space Works logo placement (AnimatedLogoMark) |
The brand signature; shows the link is live without moving layout |
| Cold-start splash opening | box-open/ |
index.html, lib/splash.ts |
First paint hands over to the header logo |
| Cold-start splash flight and fade | box-open/ |
lib/splash.ts |
The mark flies to the header logo (520 ms), then the splash fades (200 ms) |
| Box loader (loop) | box-open/ |
LogoLoader route fallbacks and panels |
One brand loading indicator |
| Box spinner and mono | box-open/ |
BoxSpinner (buttons, rows, fields) |
Inline and in-button busy state |
| Theme switch reveal | theme-reveal/ |
themeReveal.ts, themeTransition.ts |
The new theme grows from the toggle |
| Animated search field | search/ |
Shared search field | See its README |
| Route transition (View Transition) | route-transition/ |
lib/motion/*, motionRoute.css |
A page change reads as one move; chrome stays still |
Route fallback fade (sw-route-enter) |
route-transition/ |
Back and forward, unwrapped links | Same move without the API |
| Scroll restoration | route-transition/ |
ScrollManager.tsx |
Back returns to where you were |
| Root cross-fade | route-transition/ |
delight.css |
Non-route View Transitions fade the page (180 ms) |
| Stagger rise | page-enter/ |
StaggerGroup, layouts.css |
First load reads as assembled in order |
| Facet entrance | page-enter/ |
BrandFacets, fields.css |
Sign-in panel entrance, once |
| Showcase rise | page-enter/ |
fields.css (sw-auth-showcase) |
Sign-in cards arrive in turn |
| Areas panel wipe | page-enter/ |
AreasSection, hub.css |
A switched area is noticed |
| Story proof rise | page-enter/ |
StorySections, hub.css |
A new proof row lands |
| Handover wizard step change | page-enter/ |
HandoverWizard.tsx |
Shared fade and rise tokens |
| Pinned hero sequence | scroll-reveal/ |
HeroSection, useScrollSequence |
Promise to console to overview in one scene |
| Handover steps beside sticky record | scroll-reveal/ |
HandoverScrolly |
The evidence trail forms as steps pass |
| Reveal on scroll | scroll-reveal/ |
data-reveal blocks |
Sections arrive once |
| Smooth scroll to target | scroll-reveal/ |
HandoverScrolly, JoinButton, kiosk recovery, print request |
Bring the result into view |
| Scrim fade | overlays/ |
Dialogs, drawers, docs drawer scrim | The layer arrives without a jump |
| Dialog pop | overlays/ |
Modal, FilterPopover, PresenceCheckInSheet |
Arrives from just in front |
| Bottom sheet | overlays/ |
Dialogs under 640 px | Rises from the edge it docks to |
| Drawer (right and left) | overlays/ |
DetailDrawer, SidebarDrawer, DocsLayout |
Slides from its own edge |
| Menu and popover | overlays/ |
OverflowMenu, user menu, popovers |
Drops 4 px from the trigger |
| Presence (exit keeps mounted) | overlays/ |
usePresence.ts |
Exits can play and the layer is inert while closing |
| Status toast | toast/ |
ToastHost |
Status without stealing focus |
| Sliding indicator (sidebar) | sidebar/ |
Sidebar, useSlideIndicator |
One box shows the current section |
| Tab underline slide | sidebar/ |
Staff panel tabs | Same hook on tabs |
| Section collapse | collapse/ |
Collapse, Disclosure, sidebar “More” |
A group opens without losing neighbours |
| Disclosure chevrons | collapse/ |
Sidebar, collapsible and inspector sections, FAQ, docs nav | The arrow reports the state |
| Skeleton placeholder | skeleton/ |
Skeleton, DataTable loading rows |
Reserves the shape; box spinner inside |
| Progress width | skeleton/ |
cardJobs.tsx |
Progress eases to its value |
| Press and hover colour | hover-press/ |
Buttons, tabs, nav items (motion.css) |
The control answers; press sinks to 0.98 |
| Hover colour on cards, rows, links, tabs | hover-press/ |
Space cards, hub, docs, directory, settings nav | Same colour-only rule |
| Hover opacity and drag dim | hover-press/ |
Analytics bars, crew rows | Marks the hovered or dragged item |
| Card verify stamp | feedback/ |
CardVerifyPage |
A valid check lands with one stamp |
| Return confetti | feedback/ |
ReturnConfetti |
Celebrates a completed return (delight on only) |
| Result arrive, pass tear, logbook open | feedback/ |
delight.css |
Small human moments (delight on only) |
| Logo flap spring and pop | delight/ |
logoUnfold.css |
Playful flaps (delight on only) |
| Patch: pet walk, naps, paw prints | delight/ |
NotFoundPatch |
The 404 pet |
| Patch moment trot | delight/ |
PatchMoment |
Still moment that trots once |
| Patch “z” | delight/ |
patch.css |
Sleeping decoration (loops, decorative) |
| Companion walk | delight/ |
Companion |
Decorative walk (loops, decorative) |
| Glyph tilt | delight/ |
delight.css |
-3 deg under the pointer |
| Card tilt and flip | delight/ |
HolographicCard |
The printed card follows the pointer |
| Display slide fade | kiosk-display/ |
spaceDisplay/display.css |
One fade per slide; a Pi stays idle |
| Kiosk and TV token override | kiosk-display/ |
.sw-kiosk, .sw-tv |
Fades only on shared screens |
Previews and checks
Section titled “Previews and checks”Animated WebP and GIF previews (light and dark, each under 400 KB) are in every folder’s previews/. They are
rendered in headless Edge from the same CSS by node scripts/make-previews.mjs motion-kit, with every CSS
animation and transition paused and seeked to an exact time per frame. node scripts/check-previews.mjs fails when
any family’s CSS, demo page or preview is stale or missing.
Using a family
Section titled “Using a family”- Link
tokens/tokens.css(it defines the motion tokens and both themes: dark is the classdarkon<html>). - Link the family stylesheet and copy the markup from its
demo.html. - Check it in light and dark, and with
prefers-reduced-motion: reduce.
Current motion flow (decision 399)
Section titled “Current motion flow (decision 399)”Current rule (v2.0.1, 2026-11-13): The “copied unchanged” descriptions above record the original kit. Decision 399 repairs portable CSS, React reference copies and demos with token-derived timings, interruptible transitions, accessible behaviour and static image posters. Use motion-flow, the dated family addenda and current executable recipes; see current rules. Historical catalogue rows and assets remain available. Box-open is owned and verified by the logo lane.
Run node scripts/check-motion-flow.mjs --browser from the repository root. Use --require-browser to require the browser scenarios in a capable environment. The orchestrator regenerates animated previews after all lanes finish; posters are separate still assets.