chore: improve animation of blurred overlay
This commit is contained in:
@@ -1,20 +1,26 @@
|
||||
'use client'
|
||||
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import React, { ReactNode, useEffect, useState } from 'react'
|
||||
import { motion, Variants } from "framer-motion";
|
||||
import clsx from 'clsx';
|
||||
|
||||
export type BlurredOverlayContainerProps = {
|
||||
visible: boolean
|
||||
bgOpacity?: string
|
||||
changeDelay?: string
|
||||
effectdelay?: string
|
||||
} & React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>
|
||||
bgOpacity?: number
|
||||
inDelay?: number
|
||||
outDelay?: number
|
||||
transitionDelay?: number
|
||||
children: ReactNode
|
||||
} & React.ComponentProps<typeof motion.div>
|
||||
|
||||
const BlurredOverlayContainer = ({
|
||||
visible = true,
|
||||
bgOpacity = '30',
|
||||
changeDelay = '0',
|
||||
effectdelay = '0',
|
||||
bgOpacity = 30,
|
||||
inDelay = 0,
|
||||
outDelay = 0,
|
||||
transitionDelay: transitionDelay = 0,
|
||||
children,
|
||||
className,
|
||||
onClick,
|
||||
...props
|
||||
}: BlurredOverlayContainerProps) => {
|
||||
@@ -23,34 +29,55 @@ const BlurredOverlayContainer = ({
|
||||
useEffect(() => {
|
||||
if (visible) {
|
||||
// Show immediately or after delay
|
||||
const timeout = setTimeout(() => setLoaded(true), +changeDelay)
|
||||
const timeout = setTimeout(() => setLoaded(true), inDelay)
|
||||
return () => clearTimeout(timeout)
|
||||
} else {
|
||||
// Hide with delay (matches opacity transition duration)
|
||||
const timeout = setTimeout(() => setLoaded(false), +changeDelay) // 300ms matches Tailwind transition
|
||||
const timeout = setTimeout(() => setLoaded(false), outDelay) // 300ms matches Tailwind transition
|
||||
return () => clearTimeout(timeout)
|
||||
}
|
||||
}, [visible, changeDelay])
|
||||
}, [visible, inDelay, outDelay])
|
||||
|
||||
const zClass =
|
||||
visible || loaded ? 'z-50' : !visible && !loaded ? '-z-50' : 'z-0'
|
||||
const variants: Variants = {
|
||||
hidden: {
|
||||
opacity: 0,
|
||||
transition: {
|
||||
delay: transitionDelay / 1000,
|
||||
duration: 0.3,
|
||||
ease: 'easeInOut',
|
||||
},
|
||||
},
|
||||
visible: {
|
||||
opacity: 1,
|
||||
transition: {
|
||||
delay: transitionDelay / 1000,
|
||||
duration: 0.3,
|
||||
ease: 'easeInOut',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
<motion.div
|
||||
data-visible={visible}
|
||||
data-loaded={loaded}
|
||||
className={props.className + `
|
||||
fixed inset-0 flex items-center justify-center h-dvh w-full
|
||||
backdrop-blur-sm
|
||||
opacity-0 transition-opacity duration-300 ease-in-out delay-${effectdelay}
|
||||
${zClass}
|
||||
${visible ? 'opacity-100' : 'opacity-0'}`}
|
||||
style={{ backgroundColor: `rgba(0, 0, 0, ${+bgOpacity / 100})` }}
|
||||
className={clsx(
|
||||
className,
|
||||
visible || loaded ? 'z-50' : !visible && !loaded ? '-z-50' : 'z-0',
|
||||
'fixed inset-0 flex items-center justify-center h-dvh w-full backdrop-blur-sm',
|
||||
)}
|
||||
style={{
|
||||
backgroundColor: `rgba(0, 0, 0, ${bgOpacity / 100})`,
|
||||
}}
|
||||
|
||||
initial={visible ? 'visible' : 'hidden'}
|
||||
animate={visible ? 'visible' : 'hidden'}
|
||||
variants={variants}
|
||||
{...props}
|
||||
>
|
||||
<div className='w-full h-dvh overflow-hidden' onClick={onClick}></div>
|
||||
{children}
|
||||
</div>
|
||||
</motion.div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user