dbx/docs/components/landing/RevealSection.tsx

40 lines
1.2 KiB
TypeScript

"use client";
import type { ComponentPropsWithoutRef, CSSProperties, ReactNode } from "react";
import { useEffect, useRef, useState } from "react";
type RevealSectionProps = Omit<ComponentPropsWithoutRef<"section">, "children" | "className"> & {
children: ReactNode;
className?: string;
delay?: number;
};
export function RevealSection({ children, className = "", delay = 0, ...sectionProps }: RevealSectionProps) {
const ref = useRef<HTMLElement | null>(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.unobserve(entry.target);
}
},
{ rootMargin: "0px 0px -14% 0px", threshold: 0.18 },
);
observer.observe(node);
return () => observer.disconnect();
}, []);
return (
<section {...sectionProps} ref={ref} className={`${className} landing-reveal${visible ? " is-visible" : ""}`} style={{ ...sectionProps.style, "--reveal-delay": `${delay}ms` } as CSSProperties}>
{children}
</section>
);
}