Search code examples
reactjstypescriptframer-motion

Override the transition delay in React Framer Motion


I created motion.div component, which contains initial, animate and whileTap properties:

<motion.button
  initial={'initial'}
  animate={'in'}
  whileTap={'onTap'}
  variants={introButtonVariants}
>...</>

in variation contains transition with the delay: 0.5:

in: {
  x: 0,
  scale: 1,
  transition: { duration: 0.5, delay: 0.5 }
}

But this delay: 0.5 is affecting onTap variation, even if I explicitly specify new delay there. So on tap, it instantly goes in the "tapped" mode but then it stops for 0.5s. before backward animation.

onTap: {
  scale: 0.8,
  transition: { scale: { delay: 0 } }
}

How can the delay value, which goes to animate property, be overridden by the new one, which is defined in the new variation?


Solution

  • Was faced with the same problem and found an answer in official discord. Looks like at this moment it's only possible with spread operator to reset delay in animate state.

    Here is a working example: https://codesandbox.io/s/motion-transition-70yhg?file=/src/App.js

    Copypaste:

    const size = 200;
    const radius = 40;
    const color = "#0CF";
    const curve = {
        type: "spring",
        stiffness: 400,
        damping: 30
    };
    
    export default function App() {
        const variants = {
            active: { scale: 1.25, transition: { ...curve, delay: 2 } },
            hovering: {
                scale: 1.5,
                rotate: 180,
                transition: { ...curve, delay: 0 }
            }
        };
    
        return (
            <div className="App">
                <motion.div
                    style={{
                        width: size,
                        height: size,
                        backgroundColor: color,
                        borderRadius: radius
                    }}
                    variants={variants}
                    animate={"active"}
                    whileHover={"hovering"}
                    transition={{ ...curve }}
                />
            </div>
        );
    }