Contact Us

Animation Layer

DOC-00106 guide implementor, developer

Overview

The project uses Motion Mini (motion/mini) as its animation engine, decoupled from the component interactivity layer.

All core animation consumers import from src/lib/motion.ts, not directly from motion/mini. The wrapper provides a reduced-motion guard that covers WAAPI animations (the existing CSS rule in base.css only covers CSS animations).

Scroll-Reveal Utility

The primary API is revealOnScroll() from src/lib/motion-reveal.ts. It wires IntersectionObserver to Motion Mini’s animate() for viewport-triggered animations.

import { revealOnScroll } from "@/lib/motion-reveal";

// Named preset
revealOnScroll(".cards", "fade-up");

// With options
revealOnScroll(".cards", "fade-up", {
  duration: 0.8,
  stagger: 0.1,
  threshold: 0.2,
});

// Raw keyframes
revealOnScroll(".hero-element", {
  opacity: [0, 1],
  transform: ["rotate(-5deg) scale(0.8)", "rotate(0deg) scale(1)"],
});

Available Presets

Preset names are a stable API contract.

PresetEffect
fade-inOpacity 0 to 1
fade-upFade + slide up from below
fade-downFade + slide down from above
fade-leftFade + slide from the right
fade-rightFade + slide from the left
slide-upSlide up 40px (no fade)
slide-downSlide down 40px (no fade)
slide-leftSlide from right 40px (no fade)
slide-rightSlide from left 40px (no fade)
scale-inFade + scale from 0.9
scale-upFade + scale from 0.8

Child sites can pass additional presets at call time:

revealOnScroll(".element", "bounce-in", {
  presets: {
    "bounce-in": {
      keyframes: { opacity: [0, 1], transform: ["scale(0.5)", "scale(1)"] },
      duration: 0.6,
      ease: "backOut",
    },
  },
});

Options

OptionTypeDefaultDescription
oncebooleantrueAnimate only on first intersection
thresholdnumber0.1IntersectionObserver threshold (0–1)
rootMarginstring"0px"IntersectionObserver root margin
durationnumber0.5Duration in seconds (overrides preset)
delaynumber0Delay in seconds
easeEasing"easeOut"Motion easing function
staggernumberStagger interval in seconds per element
presetsRecordAdditional presets for this call

Direct animate() Usage

For animations beyond scroll-reveal, import animate directly from the wrapper:

import { animate, stagger } from "@/lib/motion";

// Animate specific elements
animate(".logo", { scale: [1, 1.1, 1] }, { duration: 0.3 });

// With stagger delay
animate(".nav-item", { opacity: [0, 1] }, { delay: stagger(0.05) });

Reduced Motion

Two complementary layers ensure accessibility:

  1. CSS layerbase.css forces animation-duration: 0.01ms on all elements when prefers-reduced-motion: reduce is active. This covers CSS animations and transitions.
  2. JS layer — The motion.ts wrapper checks prefers-reduced-motion at each animate() call. When active, it sets duration: 0 so elements reach their final state instantly. The check runs at call time, so runtime preference changes are respected.

View Transitions

The revealOnScroll utility manages its own lifecycle for View Transitions (ClientRouter). On astro:page-load, it disconnects stale observers and re-applies all registrations against the new DOM. Callers do not need to re-invoke after a page swap.

Direct animate() callers manage their own lifecycle. Use astro:before-swap for cleanup and astro:page-load for re-initialization, following the same pattern as other project modules.

Progressive Enhancement

Elements start visible — no CSS pre-hide state. Users with JS disabled see all content normally. Elements already in the viewport when revealOnScroll is called are marked as revealed and skip animation, preventing a visible-then-invisible flash.

Upgrade Path

The motion npm package is installed in core. Child sites can import from deeper paths without adding a dependency:

  • motion/mini — WAAPI-only engine (~2.3 KB)
  • motion — full hybrid JS engine with inView, stagger, scroll (~17 KB)
  • motion/react — React component API for React islands
REQ-00085 normative Reduced motion preferences shall be respected.
REQ-00268 implemented The theme shall provide a scroll-reveal animation utility that animates elements as they enter the viewport, with named presets for common entrance patterns (fade, slide, scale variants) and support for custom keyframes.
REQ-00269 implemented Motion Mini (motion/mini) shall be the approved animation engine for WAAPI-based animations, providing a reduced-motion-aware animate() wrapper.

Search

Search across pages and articles. Use arrow keys to navigate results.

Search across pages and articles.

Loading search...

Search is unavailable. Please try again later.

    No results for ""

    Try different keywords or fewer words.