ENOK · Asset Foundry

Transitions Kit

Copy-paste motion for real apps — page fades, scroll reveals, list springs, modal physics, and now the component moments too: toasts, sliding tabs, accordions, tooltips, error shake, and skeleton crossfade. Two files, zero dependencies, CSP-safe. Every recipe respects prefers-reduced-motion, and every component rides its own shadow — no global dim.

v0.2 · 10 recipes · transitions.css + transitions.js · no build step
Recipe 01

Page enter

This page just did it. Put .tx-page on your top wrapper — the whole view fades and rises in on load. On supporting browsers it also opts into the native cross-document View Transitions API.

<!-- one class, that's the whole recipe -->
<body class="tx-page"> … </body>
Recipe 02

Staggered reveals on scroll

Scroll the cards into view — each fades up a beat after the last. Wrap them in data-tx-stagger, tag each with tx-reveal. transitions.js numbers them and reveals via IntersectionObserver. No JS to write.

Fade upThe default reveal — opacity + a 14px rise.
StaggeredEach item waits --tx-i × 60ms.
Scale inAdd tx-scale to grow from 94%.
From leftAdd tx-left or tx-right.
Observer-drivenFires once, then unobserves. Cheap.
Motion-safeReduced-motion shows them instantly.
<div data-tx-stagger>
  <div class="tx-reveal">…</div>
  <div class="tx-reveal tx-scale">…</div>
</div>
/* or drive it yourself: */
Transitions.reveal(".tx-reveal", { stagger: 60 });
Recipe 03

List spring

Same stagger, springier curve. tx-spring pops each row in with a touch of overshoot — good for freshly loaded lists and search results.

<ul data-tx-stagger>
  <li class="tx-spring">…</li>
</ul>
Recipe 04

Modal physics

Backdrop fades, panel springs up and scales in. Open with a data-tx-open button; close on the ✕, the scrim, or Esc. Focus moves in and returns on close. All wiring is in transitions.js — the markup is declarative.

<button data-tx-open="demo-modal">Open</button>

<div id="demo-modal" class="tx-modal" aria-hidden="true">
  <div class="tx-modal__scrim"></div>
  <div class="tx-modal__panel">
    … your content …
    <button data-tx-close>Close</button>
  </div>
</div>
Recipe 05

Toasts — rise + fade + scale

Tangible cards that rise, fade, and scale into a corner region, then leave the instant they expire. They stack, they carry an optional action, and they ride their own shadow — no backdrop, no dim. All wiring is declarative via data-tx-toast.

<!-- declarative -->
<button data-tx-toast="Saved." data-tx-toast-tone="success">Save</button>

/* or from JS */
Transitions.toast("Draft saved.", { tone: "info", action: "Undo", onAction: undo });
Recipe 06

Tabs — sliding pill indicator

A pill glides under the active tab and resizes to fit it; the matching panel fades in. Arrow keys, Home/End, focus roles — all handled. Mark up data-tx-tabs and transitions.js does the measuring.

Open Procured, KPX, and Milton Leroy — free foundry type, drop-in CSS included.
This kit: page, reveal, spring, modal, toast, tabs, accordion, tooltip, shake, skeleton.
Digis and Pulse Orbs — zero-dependency components you can view-source and take.
<div data-tx-tabs>
  <div class="tx-tabs__list">
    <span class="tx-tabs__pill"></span>
    <button data-tx-tab="fonts" aria-selected="true">Fonts</button>
    <button data-tx-tab="motion">Motion</button>
  </div>
  <div data-tx-panel="fonts">…</div>
</div>
Recipe 07

Accordion — height + chevron morph

Panels animate their real height and settle to auto so they stay responsive; the chevron rotates in step. Add data-tx-accordion="single" to keep just one open at a time.

Two files, no npm, no framework, no build. Link the CSS and JS and it runs in any HTML page.
Yes — no inline handlers and no eval. Everything wires from data-attributes in transitions.js.
Every recipe collapses motion under prefers-reduced-motion. Content still shows; it just stops moving.
<div data-tx-accordion="single">
  <div class="tx-acc__item is-open">
    <button data-tx-acc-trigger>Title <span class="tx-acc__chevron">▸</span></button>
    <div class="tx-acc__panel">…</div>
  </div>
</div>
Recipe 08

Tooltip — delay in, instant out

Hover or focus and the tip appears after a short dwell; move away and it's gone at once — the asymmetry that makes tooltips feel intentional, not twitchy. One shared bubble, positioned with data-tx-tip-pos.

<button data-tx-tooltip="Appears after a dwell" data-tx-tip-pos="top">Hover</button>
/* auto-wired; or: Transitions.tooltip(el, "text", { delay: 380 }) */
Recipe 09

Error shake

A short, damped shake on its own cubic-bezier — the universal "that input was rejected" gesture. One-shot; it strips itself on animationend so it replays cleanly every time.

<input id="pw">
<button data-tx-shake="#pw">Submit</button>
/* or on a failed submit: */
if (!valid) Transitions.shake("#pw");
Recipe 10

Skeleton → content crossfade

A shimmering placeholder dissolves into the real content the moment it lands — ghost fades out as content fades in. The shimmer holds still under reduced motion.

Ora
Synced · Cloud agent
<div class="tx-skel" id="card">
  <div class="tx-skel__ghost"></div>
  <div class="tx-skel__real">… real content …</div>
</div>
/* when data arrives: */
Transitions.ready("#card");