Animation » Example Animations » 31. Animate Presence

31. Animate Presence

Here’s an example use of Animate Presence, which lets you animate an element just before it will be removed (unmounted) from the layer tree.

Code component

The smallest motion.div is wrapped inside an <AnimatePresence> component. When you give it an exit property (with the values to animate to), it will animate just before being removed (when isVisible becomes false).

export default function CC_31_Animate_Presence(props) {
    const [isVisible, setVisible] = useState(true)

    return (
        <div>
            <motion.div
                style={{
                    width: 150,
                    height: 150,
                    borderRadius: 30,
                    backgroundColor: "rgba(255,255,255,0.5)",
                    cursor: "pointer",
                }}
                onTap={() => setVisible(!isVisible)}
            >
                <AnimatePresence>
                    {isVisible && (
                        <motion.div
                            style={{
                                width: 80,
                                height: 80,
                                borderRadius: 15,
                                backgroundColor: "#fff",
                                margin: 35,
                            }}
                            initial={{ opacity: 0, scale: 0.75 }}
                            animate={{ opacity: 1, scale: 1 }}
                            exit={{ opacity: 0, scale: 0 }}
                        />
                    )}
                </AnimatePresence>
            </motion.div>
        </div>
    )
}

Code override

This override is attached to the outer frame. It wraps the (only) child of that frame inside an <AnimatePresence> and gives it the initial, animate, and exit properties.

export function Animate_Presence(Component): ComponentType {
    return (props) => {
        const { children, ...rest } = props

        const [isVisible, setVisible] = useState(true)

        return (
            <Component
                {...rest}
                onTap={() => setVisible(!isVisible)}
                children={
                    <AnimatePresence>
                        {isVisible &&
                            Children.map(children, (child) =>
                                cloneElement(child, {
                                    initial: { opacity: 0, scale: 0.75 },
                                    animate: { opacity: 1, scale: 1 },
                                    exit: { opacity: 0, scale: 0 },
                                })
                            )}
                    </AnimatePresence>
                }
            />
        )
    }
}

(You can’t just change a React element—you have to make a copy of it with cloneElement().)

Other examples of using children in a code override:


Join the Framer book mailing list    ( ± 6 emails/year )

GDPR

We use Mailchimp as our marketing platform. By clicking below to subscribe, you acknowledge that your information will be transferred to Mailchimp for processing per their Privacy Policy and Terms.



2 comments on “31. Animate Presence”

  • tibor.cseh says:

    Hi there!

    Can you tell me how can I do this by not having the modal visible the first time I launch the preview?
    I’m trying to replicate this override method for a context menu interaction by tapping on a parent and the child brings up the modal and dismisses it on the second tap.

    Thanks in advance!

    • Tes Mat says:

      That’s easy: you just set the initial value of isVisible to false (by passing a false to the useState().)

      const [isVisible, setVisible] = React.useState(false)

Leave a Reply