# How to Implement Spring Animations with Apple-Style Config in React

> Implement Apple-style spring animations in React using the Motion library. Create natural, interruptible animations with velocity and smooth retargeting. Learn how today!

- Repository: [Emil Kowalski/skills](https://github.com/emilkowalski/skills)
- Tags: tutorial
- Published: 2026-07-30

---

**Use the Motion library (formerly Framer Motion) with the configuration object `{ type: "spring", duration: 0.5, bounce: 0.2 }` to create natural, interruptible animations that carry velocity through gestures and retarget smoothly without abrupt resets.**

According to the **emilkowalski/skills** repository, spring-based motion is the preferred method for animating UI that reacts to user gestures like drag, swipe, and tap-and-hold. The repository defines a specific Apple-style spring configuration that balances perceptual settling time with subtle overshoot, ensuring interface elements feel responsive yet polished.

## Understanding the Apple-Style Spring Configuration

The canonical Apple-style spring configuration defined in [`skills/review-animations/STANDARDS.md`](https://github.com/emilkowalski/skills/blob/main/skills/review-animations/STANDARDS.md) uses a simple three-parameter object:

```javascript
{ type: "spring", duration: 0.5, bounce: 0.2 }

```

### The Physics Parameters

- **`duration`** (0.5s): Controls the perceptual time until the spring visually settles. This is not a hard timeout but rather the characteristic timescale of the decay.
- **`bounce`** (0.2): Governs the overshoot amount. A value of 0.2 provides a subtle, lively motion without distracting the user. According to the audit guidelines in [`skills/improve-animations/AUDIT.md`](https://github.com/emilkowalski/skills/blob/main/skills/improve-animations/AUDIT.md), keep bounce between 0.1 and 0.3 for most UI, reserving higher values (≈0.3) only for playful interactions like drag-to-dismiss.

## When to Use Spring Animations

Spring physics excel in gesture-driven, interruptible UI contexts where elements must maintain momentum. As documented in [`skills/apple-design/SKILL.md`](https://github.com/emilkowalski/skills/blob/main/skills/apple-design/SKILL.md), springs retain velocity and can be retargeted mid-animation without the "brick-wall" reset effect common in CSS keyframe animations.

**Use springs for:**
- Drag-to-dismiss modals and sheets
- Pull-up interactions
- Toggle switches that can be quickly reversed
- Any animation that might be interrupted by subsequent user input

**Avoid springs for:**
- Simple opacity fades or color transitions (use CSS transitions)
- Non-interruptible sequential animations
- Background loops where physics continuity is irrelevant

## Implementing Springs with Motion

The [`skills/pick-ui-library/SKILL.md`](https://github.com/emilkowalski/skills/blob/main/skills/pick-ui-library/SKILL.md) file explicitly recommends **Motion** as the go-to library because it exposes the exact `{ type, duration, bounce }` API that maps directly to the Apple-style configuration.

### Basic Implementation

Import the `animate` function and pass the Apple-style config as the third argument:

```jsx
import { animate } from "motion";

function SlidingPanel({ isOpen }) {
  const yTarget = isOpen ? 0 : 100;

  animate(
    ".panel",
    { y: yTarget },
    { type: "spring", duration: 0.5, bounce: 0.2 }
  );

  return <div className="panel">Content</div>;
}

```

This implementation mirrors the example found in [`skills/review-animations/STANDARDS.md`](https://github.com/emilkowalski/skills/blob/main/skills/review-animations/STANDARDS.md) at lines 65-68, providing a 0.5-second perceptual duration with 20% bounce.

### Handling Gesture Velocity

For draggable interfaces, you must pass the release velocity to the spring to ensure natural momentum continuation. The [`skills/apple-design/SKILL.md`](https://github.com/emilkowalski/skills/blob/main/skills/apple-design/SKILL.md) file (lines 104-110) emphasizes normalizing velocity when the API expects a fraction of the remaining distance.

```jsx
import { useSpring, motion } from "motion";
import { useState } from "react";

export default function DraggableCard() {
  const [dragging, setDragging] = useState(false);
  const x = useSpring(0, { type: "spring", duration: 0.5, bounce: 0.2 });

  return (
    <motion.div
      style={{ x }}
      drag="x"
      dragMomentum={false}
      onDragStart={() => setDragging(true)}
      onDragEnd={(event, info) => {
        setDragging(false);
        // Pass release velocity (px/s) back into the spring
        x.set(info.velocity.x, { velocity: info.velocity.x });
      }}
    />
  );
}

```

The `info.velocity.x` value carries the gesture's momentum into the spring physics, creating a seamless transition from user control to automated animation.

### Centralizing Configuration Constants

To ensure consistency across your codebase, define the Apple-style spring as a constant:

```javascript
// src/constants/animation.js
export const APPLE_SPRING = { type: "spring", duration: 0.5, bounce: 0.2 };

```

```jsx
import { animate } from "motion";
import { APPLE_SPRING } from "./constants/animation";

animate(element, { opacity: 1, scale: 1 }, APPLE_SPRING);

```

This pattern, referenced in [`skills/emil-design-eng/SKILL.md`](https://github.com/emilkowalski/skills/blob/main/skills/emil-design-eng/SKILL.md), makes global adjustments trivial—changing the bounce value in one place updates every animation using the constant.

## Accessibility Considerations

Spring animations must respect user motion preferences. Wrap spring-based components in `@media (prefers-reduced-motion: reduce)` queries as specified in [`skills/apple-design/SKILL.md`](https://github.com/emilkowalski/skills/blob/main/skills/apple-design/SKILL.md) (lines 203-207).

Replace springs with simple opacity cross-fades or static state changes when reduced motion is requested:

```css
@media (prefers-reduced-motion: reduce) {
  .spring-animated {
    transition: opacity 0.1s linear;
    /* Disable spring physics */
    transition-timing-function: linear;
  }
}

```

This ensures compliance with accessibility standards while preserving the enhanced experience for users who prefer motion.

## Summary

- **Use Motion** (formerly Framer Motion) to implement Apple-style springs in React, as it natively supports the `{ type: "spring", duration: 0.5, bounce: 0.2 }` API.
- **Reference [`skills/review-animations/STANDARDS.md`](https://github.com/emilkowalski/skills/blob/main/skills/review-animations/STANDARDS.md)** for the canonical configuration defaults and physics rationale.
- **Preserve gesture velocity** by passing release velocity to the spring's `velocity` option, ensuring natural momentum as documented in [`skills/apple-design/SKILL.md`](https://github.com/emilkowalski/skills/blob/main/skills/apple-design/SKILL.md).
- **Centralize configs** in constants files to maintain consistency and simplify global tweaks.
- **Support reduced motion** by disabling spring physics for users with motion sensitivity preferences.

## Frequently Asked Questions

### What library does the emilkowalski/skills repository recommend for spring animations?

According to [`skills/pick-ui-library/SKILL.md`](https://github.com/emilkowalski/skills/blob/main/skills/pick-ui-library/SKILL.md), the repository recommends **Motion** (formerly Framer Motion) because it exposes a `{ type, duration, bounce }` API that maps directly to the Apple-style configuration without requiring manual physics calculations.

### How do I handle bounce values for different types of interactions?

Keep bounce subtle at **0.2** for standard UI elements like toggles and sheets to avoid visual noise. Reserve higher bounce values around **0.3** only for playful, bouncy interactions such as drag-to-dismiss gestures, as advised in the audit guidelines at [`skills/improve-animations/AUDIT.md`](https://github.com/emilkowalski/skills/blob/main/skills/improve-animations/AUDIT.md).

### Why should I use springs instead of CSS transitions for gesture-based animations?

Springs carry **velocity** through interruptions and can be retargeted smoothly, whereas CSS keyframes create a "brick-wall" reset effect when interrupted. This behavior is critical for drag gestures and any UI that might receive rapid, successive inputs.

### How do I make spring animations accessible?

Wrap spring-based components in `@media (prefers-reduced-motion: reduce)` media queries and replace spring physics with simple opacity cross-fades or instant state changes. The [`skills/apple-design/SKILL.md`](https://github.com/emilkowalski/skills/blob/main/skills/apple-design/SKILL.md) file explicitly requires this pattern at lines 203-207 for accessibility compliance.