Some Examples » 29. Cycling parent and child variants

29. Cycling parent and child variants

Another example of automatic animation propagation with variants, here in combination with useCycle().

Code component

export default function CC_29_Cycling_parent_and_child_variants(props) {
    const [current, cycle] = useCycle("off", "on")

    return (
        <motion.div
            style={{
                width: 51,
                height: 31,
                borderRadius: 16,
                backgroundColor: "rgba(120,120,128,.16)",
                position: "relative",
                cursor: "pointer",
            }}
            animate={current}
            initial={false}
            onTapStart={cycle}
        >
            <motion.div
                style={{
                    width: "100%",
                    height: "100%",
                    borderRadius: 16,
                    backgroundColor: "#34C759",
                }}
                variants={{ off: { scale: 0 }, on: { scale: 1 } }}
                transition={{ ease: "easeInOut" }}
            />
            <motion.div
                style={{
                    width: 27,
                    height: 27,
                    borderRadius: 16,
                    backgroundColor: "white",
                    boxShadow: `0 0 0 0.5px rgba(0,0,0,.04), 
                         0 3px 8px 0 rgba(0,0,0,.15), 
                         0 3px 1px 0 rgba(0,0,0,.06)`,
                    position: "absolute",
                    top: 2,
                    left: 2,
                }}
                variants={{ off: { x: 0 }, on: { x: 20 } }}
                transition={{ ease: "easeInOut" }}
            />
        </motion.div>
    )
}

Code overrides

When you tap the Switch(), it does a cycle() to the next variant label. And the children (Background() and Knob() overrides) will follow along, just because they have the same variant labels: "off" and "on".

Note that the override for the parent frame, Switch(), doesn’t even have an animation.

By the way, I used the onTapStart() event so that the animation already starts when you press down.

export function Switch(Component): ComponentType {
    return (props) => {
        const [current, cycle] = useCycle("off", "on")

        return (
            <Component
                {...props}
                initial={false}
                animate={current}
                onTapStart={cycle}
            />
        )
    }
}

export function Background(Component): ComponentType {
    return (props) => {
        return (
            <Component
                {...props}
                variants={{ off: { scale: 0 }, on: { scale: 1 } }}
                transition={{ ease: "easeInOut" }}
            />
        )
    }
}

export function Knob(Component): ComponentType {
    return (props) => {
        return (
            <Component
                {...props}
                variants={{ off: { x: 0 }, on: { x: 20 } }}
                transition={{ ease: "easeInOut" }}
            />
        )
    }
}

Join the Mighty Guides 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.



Leave a Reply