Motion
Declarative animation in one patch — the Domphy equivalent of framer-motion's <motion.div animate={…}>. Describe the target keyframe; the patch animates to it with the Web Animations API. Enter, exit, and reactive re-animation are wired through Domphy's native lifecycle (_onMount, _onBeforeRemove), so there is no <AnimatePresence> wrapper and no dependency — just the browser's WAAPI.
Props
motion({
initial?: MotionKeyframe, // start state, applied before the enter animation
animate?: MotionKeyframe | State<MotionKeyframe>, // target; pass a State to re-animate on change
exit?: MotionKeyframe, // animated to right before removal
transition?: { duration?, delay?, easing?, iterations? }, // duration/delay in ms
})
A MotionKeyframe uses shorthands x / y (px), scale, rotate (deg) — composed into one transform — plus any raw CSS property (opacity, backgroundColor, …):
{ x: 100, scale: 1.2, opacity: 1 } // -> transform: translateX(100px) scale(1.2); opacity: 1
Enter
initial → animate plays on mount:
{ div: "Card", $: [motion({ initial: { opacity: 0, y: 20 }, animate: { opacity: 1, y: 0 } })] }
Exit
exit plays before the node is removed — Domphy holds the DOM until the animation finishes (via _onBeforeRemove), then removes it. Put the element behind reactive children so it can unmount:
{
div: (l) => visible.get(l) ? [{
div: "Toast",
$: [motion({ initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 } })],
_key: "toast",
}] : [],
}
Reactive animate
Pass a State as animate and the element re-animates to the new keyframe whenever the state changes — the declarative animate={value} pattern:
const pos = toState({ x: 0 })
{ div: "Box", $: [motion({ animate: pos })] }
// later:
pos.set({ x: 160 }) // smoothly animates across
Scope
motion covers the declarative animate / initial / exit core. Reorder/layout (FLIP) animations are handled by transitionGroup; hover/tap use CSS :hover / :active; scroll- and drag-driven animation compose from IntersectionObserver / pointer events with the same WAAPI inside any lifecycle hook.
No-op when the Web Animations API is unavailable (e.g. very old runtimes / non-DOM SSR) — the element simply renders without animating.