Skip to content

Commit

Permalink
refactor(landing): AnimationsController change animationState to canR…
Browse files Browse the repository at this point in the history
…un and remove shouldRegisterAnimationAnd
  • Loading branch information
bohdancho committed Aug 26, 2024
1 parent 9b185f0 commit 54c6a37
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ export function ResultsAnimation() {
toRotation='11deg'
toLeft='0%'
toTop='52%'
shouldRegisterAnimationEnd
>
Average time
</ResultsAnimationItem>
Expand Down Expand Up @@ -114,13 +113,11 @@ function ResultsAnimationItem(
| 'toRotation',
string
> & {
shouldRegisterAnimationEnd?: boolean
children: string
},
) {
return (
<AnimationItem
shouldRegisterAnimationEnd={props.shouldRegisterAnimationEnd}
block='results'
style={
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ export function ScramblesAnimation() {
<div className='relative h-full'>
<AnimationItem
block='scrambles'
shouldRegisterAnimationEnd
className='animate-landing-features-scrambles absolute right-12 top-[40%] whitespace-nowrap text-[2rem] text-grey-20'
>
R' B U L' U' D2 R' U D2 B' U2 D2 L2 F'
Expand Down
44 changes: 23 additions & 21 deletions src/features/landing/sections/FeaturesSection/animations.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,21 @@ import { createContext, ReactNode, useRef, useState, useEffect, useContext, Comp
import { type BlockType } from '.'

type AnimationContextType = {
animationState: Record<BlockType, 'waiting' | 'can-run'>
canRun: Record<BlockType, boolean>
blocksRef: BlocksRef
onAnimationEnd: () => void
onAnimationEnd: (block: BlockType) => void
}

const AnimationContext = createContext<AnimationContextType | null>(null)

type BlocksRef = Map<BlockType, Element | null>
export function AnimationsController({ children }: { children: ReactNode }) {
const blocksRef = useRef<BlocksRef>(new Map())
const [state, setState] = useState<AnimationContextType['animationState']>({
results: 'waiting',
scrambles: 'waiting',
leaderboards: 'waiting',
sharing: 'waiting',
const [canRun, setCanRun] = useState<AnimationContextType['canRun']>({
results: false,
scrambles: false,
leaderboards: false,
sharing: false,
})
const [queue, setQueue] = useState<BlockType[]>(['results', 'scrambles', 'leaderboards', 'sharing'])

Expand All @@ -29,7 +29,7 @@ export function AnimationsController({ children }: { children: ReactNode }) {

const observer = new IntersectionObserver(
([{ isIntersecting }]) => {
if (isIntersecting) setState({ ...state, [currentBlock]: 'running' })
if (isIntersecting) setCanRun({ ...canRun, [currentBlock]: true })
},
{
rootMargin: '-72px 0px 0px',
Expand All @@ -41,12 +41,15 @@ export function AnimationsController({ children }: { children: ReactNode }) {
return () => observer.unobserve(currentBlockNode)
}, [queue])

function onAnimationEnd() {
setQueue((prev) => prev.slice(1))
function onAnimationEnd(block: BlockType) {
setQueue((prev) => {
const currentBlock = prev[0]
return currentBlock === block ? prev.slice(1) : prev
})
}

return (
<AnimationContext.Provider value={{ animationState: state, onAnimationEnd, blocksRef: blocksRef.current }}>
<AnimationContext.Provider value={{ canRun, onAnimationEnd, blocksRef: blocksRef.current }}>
{children}
</AnimationContext.Provider>
)
Expand Down Expand Up @@ -75,35 +78,34 @@ export function BlockIntersectionWrapper({ children, block }: { children: ReactN
}

export function AnimationItem({
shouldRegisterAnimationEnd = false,
className,
block,
children,
...props
}: ComponentPropsWithoutRef<'div'> & { block: BlockType; shouldRegisterAnimationEnd?: boolean }) {
const { ref } = useRegisterAnimationEnd(shouldRegisterAnimationEnd)
const { animationState } = useAnimationContext()
}: ComponentPropsWithoutRef<'div'> & { block: BlockType }) {
const { ref } = useRegisterAnimationEnd(block)
const { canRun } = useAnimationContext()

return (
<div className={cn({ paused: animationState[block] === 'waiting' }, className)} ref={ref} {...props}>
<div className={cn({ paused: !canRun[block] }, className)} ref={ref} {...props}>
{children}
</div>
)
}

function useRegisterAnimationEnd(enabled: boolean) {
function useRegisterAnimationEnd(block: BlockType) {
const ref = useRef<HTMLDivElement>(null)
const { onAnimationEnd } = useContext(AnimationContext)!
const { onAnimationEnd } = useAnimationContext()

useEffect(() => {
const node = ref.current
if (!node || !enabled) {
if (!node) {
return
}
const callback = () => onAnimationEnd()
const callback = () => onAnimationEnd(block)
node.addEventListener('animationend', callback)
return () => node.removeEventListener('animationend', callback)
}, [ref, enabled])
}, [ref, block])

return { ref }
}
2 changes: 1 addition & 1 deletion src/features/landing/sections/FeaturesSection/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,5 +76,5 @@ function Feature({
}

function FakeAnimation({ block }: { block: BlockType }) {
return <AnimationItem block={block} shouldRegisterAnimationEnd className='animate-fake h-full w-full'></AnimationItem>
return <AnimationItem block={block} className='animate-fake h-full w-full'></AnimationItem>
}

0 comments on commit 54c6a37

Please sign in to comment.