React-Spring fade 2 buttons on box hover

1k views Asked by At

I have a box that contains two buttons stacked in the center. When I hover on the box, I want the buttons to transition opacity from 0 to 1 and I want to transition the transform property from translateY(20px) to translateY(0), so that they also move up. I have this effect in place, however I want to have the bottom button's animation delayed slightly when hovering, and I want the top buttons animation delayed slightly when un-hovering. How can I achieve this with react-spring?

Here is what I have

  const [isHovering, setIsHovering] = useState(false);
  const fadeStyles = useSpring({
    from: { opacity: 0, transform: `translateY(20px)` },
    to: {
      opacity: isHovering ? 1 : 0,
      transform: isHovering ? `translateY(0px)` : `translateY(20px)`,
    },
  });

  return (
    <div>
      <animated.div style={fadeStyles}>
        <Button>Change</Button>
      </animated.div>

      <animated.div style={fadeStyles}>
        <Button>Details</Button>
      </animated.div>
    </div>

  )
2

There are 2 answers

0
Peter Ambruzs On BEST ANSWER

It is a bit tricky question. It seems on the first glance that you could not implement it with a single useSpring function, because the different delay. You can try with the useTrail, but the trail is not easily reversible. So the useSprings remains.

The delay property is the key. You must use it with a function parameter, so you can change the delay depending the index of the button and the state of the hover. I ended up with this, it is a bit more general it creates 4 animating divs:

  const count = 4;
  const [springs, setSprings] = useSprings(count, (i) => ({
    opacity: 0.2,
    transform: `translateY(20px)`
  }));

  const onHover = (isHover) => {
    setSprings((i) => ({
      opacity: isHover ? 1 : 0.2,
      transform: isHover ? `translateY(0px)` : `translateY(20px)`,
      delay: isHover ? i * 100 : (count - 1 - i) * 100
    }));
  };

The render part:

  {springs.map((props, index) => (
    <animated.div key={index} style={props}>
      button
    </animated.div>
  ))}

working example: https://codesandbox.io/s/reversed-delay-animation-on-hover-v1phc

0
Silvia O'Dwyer On

You can make use of the delay property to specify the length of time in ms to delay the animation by:

So in your case, to delay by 80ms:

const fadeStyles = useSpring({
    delay: 80,
    from: { opacity: 0, transform: `translateY(20px)` },
    to: {
    opacity: isHovering ? 1 : 0,
    transform: isHovering ? `translateY(0px)` : `translateY(20px)`,
    },

});

See the API for more information.