web-portfolio/components/ui/reveal.tsx

50 lines
887 B
TypeScript
Raw Normal View History

'use client';
import {
useEffect,
useRef,
useState,
type CSSProperties,
type ReactNode,
} from 'react';
type Props = {
children: ReactNode;
delay?: number;
};
// Fades content up as it scrolls into view.
const Reveal = ({ children, delay = 0 }: Props) => {
const ref = useRef<HTMLDivElement>(null);
const [visible, setVisible] = useState(false);
useEffect(() => {
const node = ref.current;
if (!node) return;
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
setVisible(true);
observer.disconnect();
}
},
{ threshold: 0.12 },
);
observer.observe(node);
return () => observer.disconnect();
}, []);
return (
<div
ref={ref}
data-visible={visible}
className="reveal"
style={{ '--reveal-delay': `${delay}ms` } as CSSProperties}
>
{children}
</div>
);
};
export default Reveal;