Motion presets TypeScript helper for React
v1.0.0Added in 1.0.0
The shared springs, enter and exit presets, stagger helpers and reduced-motion hooks every animated component uses.
Four balls run the four springs side by side, so you can feel the difference. Pick a spring and a stagger step, then replay the list to see them drive real content. Everything turns into a short fade when the system asks for reduced motion.
Motion presets is a free React helper in the React hooks and utilities category, written in TypeScript for React 19. It installs as source with npx wingo-ui@latest add motion, together with useMediaQuery and the npm package motion.
Add to a project
Requirements: React 19, in Next.js (App Router or Pages), Vite or React Router. Installation guide · Next.js setup · Vite setup
npx wingo-ui@latest add motionUsage
Import springs from @/lib/motion.
import { AnimatePresence, motion } from "motion/react"
import { press, springs, useMotionPreset, useMotionTransition } from "@/lib/motion"
export function SaveMenu({ open, saved }: { open: boolean; saved: boolean }) {
const popover = useMotionPreset("popover")
const layout = useMotionTransition(springs.smooth)
return (
<motion.div layout transition={{ layout }} className="flex items-center gap-2">
<motion.button {...press}>{saved ? "Saved" : "Save"}</motion.button>
<AnimatePresence>
{open && <motion.div {...popover} className="rounded-2xl bg-popover p-4 shadow-floating" />}
</AnimatePresence>
</motion.div>
)
}API
springdefault"smooth""snappy" | "smooth" | "bouncy" | "gentle"springs[name]: snappy (500 / 32) answers a finger, smooth (300 / 30) is the default for overlays and layout, bouncy (400 / 18) is for playful accents, gentle (120 / 20) for large surfaces.
staggerdefault0.04numberstaggerChildren(step, delay?): seconds between siblings. 0.03 to 0.05 feels quick; above 0.08 reads as slow.
Parts
presets
constantinitial / animate / exit / transition bundles to spread onto a motion element inside AnimatePresence. collapse animates height to auto for accordions and collapsibles, the one sanctioned height animation. Type: Record<"overlay" | "popover" | "tooltip" | "dialog" | "sheet" | "fade" | "listItem" | "toast" | "collapse", MotionPreset>.
sheetFrom
functionThe sheet preset for any edge. Signature: (side: "top" | "right" | "bottom" | "left") => MotionPreset.
press
constantThe shared press feedback: scale 0.97 on a snappy spring. Type: { whileTap, transition }.
gestures
constantShared thresholds for drags, swipes and long presses, matched to vaul: a drag completes past a quarter of the surface or on a 400px/s flick. longPress is in ms, slop in px. Type: { completeFraction: 0.25, completeVelocity: 400, elastic: 0.2, longPress: 450, slop: 8 }.
shouldComplete
functionWhether a drag should complete (dismiss, commit a swipe action) or spring back. Pass the offset and velocity along the drag axis, positive toward completion. Signature: (offset: number, velocity: number, size: number) => boolean.
rubberband
functioniOS-style resistance past an edge: maps how far the finger is past a limit to how far the surface moves. Signature: (overflow: number, dimension: number, constant?: number) => number.
easings
constantTween curves and durations in seconds, matching the --motion-* CSS tokens. Type: { out, inOut, sheet }.
durations
constantTween curves and durations in seconds, matching the --motion-* CSS tokens. Type: { fast: 0.15, normal: 0.24, slow: 0.4 }.
staggerItem
constantChild variants for staggerChildren, and a capped per-index delay for items that animate on their own. Type: Variants.
staggerDelay
functionChild variants for staggerChildren, and a capped per-index delay for items that animate on their own. Signature: (index: number, step?: number, max?: number) => number.
usePrefersReducedMotion
hookThe reduced-motion preference, false on the server and during hydration so markup matches. Signature: () => boolean.
useMotionPreset
hookA preset that turns into a short opacity fade under reduced motion. reducePreset(preset, reduced) is the same without the hook. Signature: (preset: PresetName | MotionPreset) => MotionPreset.
useMotionTransition
hookThe transition you pass, or an instant one under reduced motion. For layout animations and indicators. Signature: (transition?: Transition) => Transition.
Examples
Cart rows
useMotionPreset("listItem") with layout: new rows slide in, removed rows leave and the rest close the gap.
Dependencies
Files
- lib/motion.ts
FAQ
Is the Motion presets helper free?
Yes. The source is free and needs no account: copy it from the Code tab or install it with the CLI.
How do I install Motion presets?
Run npx wingo-ui@latest add motion. It also adds the Wingo UI item it builds on (useMediaQuery) and the npm package motion. With shadcn, run npx shadcn@latest add https://wingo-ui.com/r/motion.json.
See also
Used in
More React hooks and utilities
Articles using this component
- Framer Motion Spring Presets: Stiffness and Damping
Component guides9 min read
- Prefers Reduced Motion React: Calm Motion, No Mismatch
Next.js and Tailwind CSS8 min read