diff --git a/apps/frontpage/components/home/hero/manager/component.tsx b/apps/frontpage/components/home/hero/manager/component.tsx index 9a0ede4b..78858fa0 100644 --- a/apps/frontpage/components/home/hero/manager/component.tsx +++ b/apps/frontpage/components/home/hero/manager/component.tsx @@ -1,3 +1,4 @@ +import type { ValueAnimationTransition } from 'framer-motion'; import { motion, useAnimate } from 'framer-motion'; import { useEffect } from 'react'; import { ComponentImage } from './component-image'; @@ -11,33 +12,63 @@ export const Component = () => { const [scopeAddToCart, animateAddToCart] = useAnimate(); useEffect(() => { - void (async () => { - await animate( - scope.current, + let isCancelled = false; + + const enterAnimation = async () => { + const animateIfNotCancelled = async ( + animation: { opacity?: number; y?: number; fill?: string }, + options: ValueAnimationTransition, + ) => { + if (!isCancelled && scope.current) { + await animate(scope.current, animation, options); + } + }; + + await animateIfNotCancelled( { opacity: 1, y: 0, fill: '#000' }, { duration: DURATION, delay: DELAY }, ); - await animate( - scope.current, + await animateIfNotCancelled( { fill: '#fff' }, { duration: DURATION, delay: 1.15 }, ); - })(); + }; + + void enterAnimation(); + + return () => { + isCancelled = true; + }; }, [animate, scope]); useEffect(() => { - void (async () => { - await animateAddToCart( - scopeAddToCart.current, + let isCancelled = false; + + const enterAnimation = async () => { + const animateIfNotCancelled = async ( + animation: { fill?: string; opacity?: number }, + options: ValueAnimationTransition, + ) => { + if (!isCancelled && scopeAddToCart.current) { + await animateAddToCart(scopeAddToCart.current, animation, options); + } + }; + + await animateIfNotCancelled( { opacity: 0.6, fill: '#666D82' }, { duration: DURATION, delay: DELAY }, ); - await animateAddToCart( - scopeAddToCart.current, + await animateIfNotCancelled( { fill: '#fff' }, { duration: DURATION, delay: 1.15 }, ); - })(); + }; + + void enterAnimation(); + + return () => { + isCancelled = true; + }; }, [animateAddToCart, scopeAddToCart]); return ( diff --git a/apps/frontpage/components/home/hero/manager/slide-controls.tsx b/apps/frontpage/components/home/hero/manager/slide-controls.tsx index 5a085ac2..d6ba4cdf 100644 --- a/apps/frontpage/components/home/hero/manager/slide-controls.tsx +++ b/apps/frontpage/components/home/hero/manager/slide-controls.tsx @@ -1,4 +1,5 @@ import { useEffect } from 'react'; +import type { ValueAnimationTransition } from 'framer-motion'; import { motion, useAnimate } from 'framer-motion'; import { UndoIcon } from '@storybook/icons'; import Image from 'next/image'; @@ -14,10 +15,25 @@ export const SlideControls = () => { const [scope, animate] = useAnimate(); useEffect(() => { - void (async () => { - await animate(scope.current, { y: 280 }); - await animate( - scope.current, + let isCancelled = false; + const enterAnimation = async () => { + const animateIfNotCancelled = async ( + animation: { + opacity?: number; + scale?: number; + x?: number; + y?: number; + fill?: string; + }, + options?: ValueAnimationTransition, + ) => { + if (!isCancelled && scope.current) { + await animate(scope.current, animation, options); + } + }; + + await animateIfNotCancelled({ y: 280 }); + await animateIfNotCancelled( { x: 210, y: 200, @@ -25,24 +41,29 @@ export const SlideControls = () => { }, { duration: 0.4 }, ); - await animate( - scope.current, + await animateIfNotCancelled( { scale: 0.8 }, { duration: 0.1, delay: 0.2 }, ); - await animate(scope.current, { scale: 1 }, { duration: 0.1 }); - await animate( - scope.current, + await animateIfNotCancelled({ scale: 1 }, { duration: 0.1 }); + await animateIfNotCancelled( { x: 240, y: 256 }, { duration: 0.1, delay: 1 }, ); - await animate( - scope.current, + await animateIfNotCancelled( { scale: 0.8 }, { duration: 0.1, delay: 0.2 }, ); - await animate(scope.current, { scale: 1 }, { duration: 0.1 }); - })(); + await animateIfNotCancelled({ scale: 1 }, { duration: 0.1 }); + }; + + if (scope.current) { + void enterAnimation(); + } + + return () => { + isCancelled = true; + }; }, [animate, scope]); return (