# Motion presets

> The shared springs, enter and exit presets, stagger helpers and reduced-motion hooks every animated component uses.

- Type: React helper (Hooks & Utilities)
- Access: Free (the source is open to everyone)
- Version: 1.0.0
- Install: `npx wingo-ui@latest add motion`
- Docs: https://wingo-ui.com/components/motion

## Interaction

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.

## Installation

```bash
npx wingo-ui@latest add motion
```

The CLI adds the files, their dependencies and a version record for updates.

With shadcn: `npx shadcn@latest add https://wingo-ui.com/r/motion.json`

Files:

- `lib/motion.ts`

npm dependencies: `npm i motion`

Wingo UI dependencies (installed automatically):

- [useMediaQuery](https://wingo-ui.com/components/use-media-query) ([Markdown](https://wingo-ui.com/components/use-media-query.md))

## Usage

```tsx
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

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `spring?` | `"snappy" \| "smooth" \| "bouncy" \| "gentle"` | `"smooth"` | 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. |
| `stagger?` | `number` | `0.04` | staggerChildren(step, delay?): seconds between siblings. 0.03 to 0.05 feels quick; above 0.08 reads as slow. |

## Parts

### presets (constant)

initial / 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 (function)

The sheet preset for any edge. Signature: (side: "top" | "right" | "bottom" | "left") => MotionPreset.

### press (constant)

The shared press feedback: scale 0.97 on a snappy spring. Type: { whileTap, transition }.

### gestures (constant)

Shared 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 (function)

Whether 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 (function)

iOS-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 (constant)

Tween curves and durations in seconds, matching the --motion-* CSS tokens. Type: { out, inOut, sheet }.

### durations (constant)

Tween curves and durations in seconds, matching the --motion-* CSS tokens. Type: { fast: 0.15, normal: 0.24, slow: 0.4 }.

### staggerItem (constant)

Child variants for staggerChildren, and a capped per-index delay for items that animate on their own. Type: Variants.

### staggerDelay (function)

Child 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 (hook)

The reduced-motion preference, false on the server and during hydration so markup matches. Signature: () => boolean.

### useMotionPreset (hook)

A 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 (hook)

The 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.

## See also

- [useMediaQuery](https://wingo-ui.com/components/use-media-query) ([Markdown](https://wingo-ui.com/components/use-media-query.md))
- [Button](https://wingo-ui.com/components/button) ([Markdown](https://wingo-ui.com/components/button.md))
- [useControllableState](https://wingo-ui.com/components/use-controllable-state) ([Markdown](https://wingo-ui.com/components/use-controllable-state.md))

---

Canonical: https://wingo-ui.com/components/motion
More components: https://wingo-ui.com/components · Index for agents: https://wingo-ui.com/llms.txt
