Skip to content

Instantly share code, notes, and snippets.

@reyronald
Created June 18, 2021 13:37
Show Gist options
  • Save reyronald/e4792d36b016bfab6f882c7f6a9369ea to your computer and use it in GitHub Desktop.
Save reyronald/e4792d36b016bfab6f882c7f6a9369ea to your computer and use it in GitHub Desktop.
<AnimateMounting
    show={enabledNotificationsButBlacklisted}
    animate={({ el, show }) => {
        const duration = 150
        const easing = 'cubic-bezier(0.645, 0.045, 0.355, 1)'
        const options = { duration, easing }

        try {
        if (show) {
            return el.animate(
            [
                { transform: 'scale(0.7)', opacity: 0.1 },
                { transform: '', opacity: 1 },
            ],
            options,
            )
        } else {
            return el.animate(
            [
                { transform: '', opacity: 1 },
                { transform: 'scale(0.7)', opacity: 0.1 },
            ],
            options,
            )
        }
        } catch (err) {
        // Sometimes, even if the browser seems to support WAAPI,
        // the animation function will fail anyway
        const mockAnimation = ({
            onfinish(): void {
            /* empty */
            },
            cancel(): void {
            /* empty */
            },
        } as any) as Animation
        requestAnimationFrame(() => {
            mockAnimation.onfinish?.(null as any)
        })
        return mockAnimation
        }
    }}
>
    <Flex>
        <HeyAlertIconStyled size={23} />
        <p>{blacklistInfoText}</p>
    </Flex>
</AnimateMounting>
import React from 'react'
export type Props = {
show: boolean
children: React.ReactNode
animate(args: { el: HTMLDivElement; show: boolean }): Animation
}
export const AnimateMounting: React.FunctionComponent<Props> = ({ show, children, animate }) => {
const elRef = React.useRef<HTMLDivElement>(null)
const animateCallback = React.useRef(animate)
const [status, setStatus] = React.useState<'entering' | 'exited'>(show ? 'entering' : 'exited')
const supportsWAAPI = 'animate' in document.body
React.useLayoutEffect(() => {
const el = elRef.current
if (!el || !supportsWAAPI || status === 'exited') {
return
}
const animation = animateCallback.current({ el, show })
if (!show) {
animation.onfinish = () => {
setStatus('exited')
}
}
return () => {
if (!show) {
animation.cancel()
}
}
}, [supportsWAAPI, show, status])
React.useEffect(() => {
if (supportsWAAPI && status === 'exited' && show) {
setStatus('entering')
}
}, [supportsWAAPI, show, status])
if ((supportsWAAPI && status === 'exited') || (!supportsWAAPI && !show)) {
return null
}
return (
<div ref={elRef} style={{ overflow: 'hidden' }}>
{children}
</div>
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment