reactjsanimationreact-spring

How to reverse en animation onClose?


Context : I created a reusable component Panel that displays the content in a panel on the right of the screen.

Objective : When I open it, I added an animation from right to left as you can see. But when I close it, the Panel disappear. I would like it to do the animation entry in reverse, and then close.

What I tried

I tried the leave property, but does not change anything.

Any idea ?

Here is my component :

const Panel: React.FC<PanelProps> = ({children, onClose, classNames}) => {
    const transitions = useSpring({
        from: {transform: "translateX(100%)"},
        to: {transform: "translateX(0)"},
        config: {duration: 200},
    });

    return (
        <div className='z-10 lg:fixed lg:left-0 lg:top-0 lg:flex lg:h-screen lg:w-screen'>
            <div onClick={onClose} className='w-full bg-black opacity-40' />

            <animated.div
                className={clsx(
                    "fixed right-0 top-0 z-10 h-screen w-full overflow-y-auto bg-white shadow-lg",
                    classNames?.panelSize ?? "w-full md:w-4/12"
                )}
                style={transitions}>
                <button
                    onClick={onClose}
                    className='absolute right-6 top-6 rounded-full bg-white p-1 duration-100 ease-in hover:scale-125 '>
                    <CgClose size={20} />
                </button>

                <div>{children}</div>
            </animated.div>
        </div>
    );
};

export default Panel;

Solution

  • It is closed probably because your onClose function sets a state which unmounts the component immediately, leaving no time for the animation to run. Your could set a timeout in your onClose function and unmount the component only after the timeout is done.

    While doing that, create a new state called isClosing and update your onClose function as follows:

    const onClose = () => {
      setIsClosing(true);
      setTimeOut(() => <Function that will unmount your component>, <Your animation duration>);
    }
    

    Then, inside your panel component you could listen to isClosing and animate your element.

    const Panel: React.FC<PanelProps> = ({children, onClose, isClosing, classNames}) => {
      useEffect(() => {
        if (isClosing) {
        // Run the reverse animation function here.
      }
    }, [isClosing])}