58 lines
1.4 KiB
TypeScript
58 lines
1.4 KiB
TypeScript
"use client";
|
||
|
||
import { useEffect, useRef, useState, type ReactNode } from "react";
|
||
import { cn } from "@/lib/utils";
|
||
|
||
/**
|
||
* Landing bölümlerinin görünüme girerken yumuşakça belirmesi.
|
||
* Motion yerine CSS transition + IntersectionObserver: SSR HTML'i görünür
|
||
* gelir (JS'siz/yavaş istemcide sayfa boş kalmaz), gizleme yalnızca
|
||
* `@media (scripting: enabled)` altında yaşar (bkz. globals.css .kt-reveal).
|
||
*/
|
||
export function Reveal({
|
||
children,
|
||
delay = 0,
|
||
y = 28,
|
||
className,
|
||
}: {
|
||
children: ReactNode;
|
||
delay?: number;
|
||
y?: number;
|
||
className?: string;
|
||
}) {
|
||
const ref = useRef<HTMLDivElement>(null);
|
||
const [gorunur, setGorunur] = useState(false);
|
||
|
||
useEffect(() => {
|
||
const el = ref.current;
|
||
if (!el || typeof IntersectionObserver === "undefined") {
|
||
setGorunur(true);
|
||
return;
|
||
}
|
||
const io = new IntersectionObserver(
|
||
(entries) => {
|
||
if (entries.some((e) => e.isIntersecting)) {
|
||
setGorunur(true);
|
||
io.disconnect();
|
||
}
|
||
},
|
||
{ rootMargin: "0px 0px -80px 0px" },
|
||
);
|
||
io.observe(el);
|
||
return () => io.disconnect();
|
||
}, []);
|
||
|
||
return (
|
||
<div
|
||
ref={ref}
|
||
className={cn("kt-reveal", gorunur && "kt-reveal-in", className)}
|
||
style={{
|
||
transitionDelay: delay ? `${delay}s` : undefined,
|
||
...(y !== 28 ? { "--reveal-y": `${y}px` } : null),
|
||
} as React.CSSProperties}
|
||
>
|
||
{children}
|
||
</div>
|
||
);
|
||
}
|