/** * Shared motion presets (Fluksio design system). * * Pure data: variants and transitions consumed by `motion/react` components * across the app. Mirrors the `--ease-*` / `--duration-*` timing tokens defined * in `index.css`, so CSS transitions and JS animations stay in sync. * * This file is duplicated verbatim in `app` and `index` (the shadcn model, * see ../../DESIGN.md / the root DESIGN-GUIDELINES.md). Keep the two copies * identical; `make design-check` at the workspace root verifies it. * * Reduced motion: wrap each app root in `` so * transform/layout animations are disabled automatically when the OS requests it. */ import type { Transition, Variants } from "motion/react" /** Easing curves, mirroring the `--ease-*` tokens. */ export const easeEmphasized: [number, number, number, number] = [0.2, 0, 0, 1] export const easeStandard: [number, number, number, number] = [0.4, 0, 0.2, 1] /** Durations in seconds, mirroring the `--duration-*` tokens (ms). */ export const duration = { fast: 0.15, base: 0.2, slow: 0.3, /** One-shot feedback, not a state change. See `--duration-pulse`. */ pulse: 0.5, } as const export const transitions = { /** Enter / expressive moves (decelerate). */ emphasized: { duration: duration.base, ease: easeEmphasized }, /** Neutral state changes. */ standard: { duration: duration.base, ease: easeStandard }, /** Springy, for hover tilt / direct-manipulation feedback. */ spring: { type: "spring", stiffness: 250, damping: 20, mass: 0.5 }, } satisfies Record const exitFast: Transition = { duration: duration.fast, ease: easeStandard } /** Opacity fade. */ export const fadeIn: Variants = { hidden: { opacity: 0 }, visible: { opacity: 1, transition: transitions.standard }, exit: { opacity: 0, transition: exitFast }, } /** Fade + subtle scale: popovers, dialogs, floating panels. */ export const scaleIn: Variants = { hidden: { opacity: 0, scale: 0.96 }, visible: { opacity: 1, scale: 1, transition: transitions.emphasized }, exit: { opacity: 0, scale: 0.96, transition: exitFast }, } /** Fade + rise: list/grid items, toolbars, content blocks. */ export const slideUp: Variants = { hidden: { opacity: 0, y: 8 }, visible: { opacity: 1, y: 0, transition: transitions.emphasized }, exit: { opacity: 0, y: 8, transition: exitFast }, } /** Dialog / drawer scrim. */ export const overlayFade: Variants = { hidden: { opacity: 0 }, visible: { opacity: 1, transition: exitFast }, exit: { opacity: 0, transition: exitFast }, } /** * Stagger container for lists/grids. Children animate with `slideUp` / `fadeIn` * via `variants` inheritance (set the same `initial`/`animate` state names). */ export const listStagger: Variants = { hidden: {}, visible: { transition: { staggerChildren: 0.05, delayChildren: 0.02 } }, }