Back to Dictionary
Action Feedback
●●○Customize
Context dependent

Haptic Bounce

A physical-feeling spring animation that rapidly shrinks an element on press and bounces it back on release, mimicking a tactile physical button.

Use

Primary call-to-action buttons

Avoid

Destructive actions

Safer Alternative

No safer default listed.

Risk Level

Low risk

Live Demo

What It Is

A physical-feeling spring animation that rapidly shrinks an element on press and bounces it back on release, mimicking a tactile physical button.

When to Use

  • Primary call-to-action buttons
  • Interactive cards or app icons
  • When you want the UI to feel lively and responsive

When NOT to Use

  • Destructive actions
  • Hyperlinks in text blocks

Configuration Tips

  • 01Scale down to around 0.95 or 0.97 - not too much or it feels broken
  • 02Use a spring physics curve with high stiffness (400) and moderate damping (30)

You've Seen It In

SpotifyApple iOSDuolingo

AI Implementation Prompts

Move from a fast scaffold to production details, then tune timing and edge states.

Make this button bounce like a spring when pressed and released.

Reference Implementation

The same implementation approach used by the live preview, kept compact enough to inspect and adapt.

'use client';
import { motion } from 'framer-motion';
import { useState, useEffect } from 'react';

export function HapticBounceDemo({ isPlaying = false }: { isPlaying?: boolean }) {
    const [isPressed, setIsPressed] = useState(false);

    useEffect(() => {
        if (!isPlaying) {
            setIsPressed(false);
            return;
        }
        const interval = setInterval(() => {
            setIsPressed(true);
            setTimeout(() => setIsPressed(false), 250);
        }, 1500);
        return () => clearInterval(interval);
    }, [isPlaying]);

    return (
        <div className="flex h-64 w-full items-center justify-center rounded-2xl bg-white p-6 shadow-sm ring-1 ring-stone-200">
            <motion.button
                animate={isPressed ? { scale: 0.85 } : { scale: 1 }}
                whileTap={{ scale: 0.85 }}
                transition={{ type: "spring", stiffness: 400, damping: 10 }}
                className="min-w-[160px] rounded-xl bg-stone-900 px-10 py-4 text-base font-medium text-white shadow-sm hover:bg-stone-800"
            >
                Add to Cart
            </motion.button>
        </div>
    );
}