Fix deferred sections staying invisible after lazy mount.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
f30a7cf879
commit
11daabf065
@ -1171,6 +1171,12 @@ img { max-width: 100%; display: block; }
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
/* Deferred kits: once mounted, never stay invisible if JS timing races */
|
||||
[data-deferred="ready"] .reveal {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.deferred-skeleton {
|
||||
height: 120px;
|
||||
margin: 24px auto;
|
||||
|
||||
@ -129,9 +129,13 @@ export default function HomeClient(props: Props) {
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
// Above-fold reveal only — deferred sections self-reveal via WhenVisible
|
||||
const nodes = document.querySelectorAll(".reveal:not(.visible)");
|
||||
if (!nodes.length) return;
|
||||
// Above-fold reveal; keep watching briefly for late client mounts
|
||||
const mark = (root: ParentNode = document) => {
|
||||
root.querySelectorAll(".reveal:not(.visible)").forEach((el, i) => {
|
||||
(el as HTMLElement).style.transitionDelay = `${(i % 6) * 0.08}s`;
|
||||
});
|
||||
};
|
||||
mark();
|
||||
const observer = new IntersectionObserver(
|
||||
(entries) => entries.forEach((e) => {
|
||||
if (e.isIntersecting) {
|
||||
@ -139,13 +143,18 @@ export default function HomeClient(props: Props) {
|
||||
observer.unobserve(e.target);
|
||||
}
|
||||
}),
|
||||
{ threshold: 0.1, rootMargin: "0px 0px -40px 0px" }
|
||||
{ threshold: 0.08, rootMargin: "0px 0px -40px 0px" }
|
||||
);
|
||||
nodes.forEach((el, i) => {
|
||||
(el as HTMLElement).style.transitionDelay = `${(i % 6) * 0.08}s`;
|
||||
observer.observe(el);
|
||||
});
|
||||
return () => observer.disconnect();
|
||||
const observeAll = () => {
|
||||
document.querySelectorAll(".reveal:not(.visible)").forEach((el) => observer.observe(el));
|
||||
};
|
||||
observeAll();
|
||||
const mo = new MutationObserver(() => observeAll());
|
||||
mo.observe(document.body, { childList: true, subtree: true });
|
||||
return () => {
|
||||
observer.disconnect();
|
||||
mo.disconnect();
|
||||
};
|
||||
}, []);
|
||||
|
||||
const toggleCompare = (slug: string) => {
|
||||
|
||||
@ -29,7 +29,7 @@ export default function WhenVisible({
|
||||
io.disconnect();
|
||||
}
|
||||
},
|
||||
{ rootMargin, threshold: 0.01 }
|
||||
{ rootMargin, threshold: 0 }
|
||||
);
|
||||
io.observe(el);
|
||||
return () => io.disconnect();
|
||||
@ -37,10 +37,24 @@ export default function WhenVisible({
|
||||
|
||||
useEffect(() => {
|
||||
if (!show || !ref.current) return;
|
||||
// Reveal animations for deferred sections without a global MutationObserver
|
||||
ref.current.querySelectorAll(".reveal:not(.visible)").forEach((node) => {
|
||||
const root = ref.current;
|
||||
|
||||
const markVisible = () => {
|
||||
root.querySelectorAll(".reveal:not(.visible)").forEach((node) => {
|
||||
node.classList.add("visible");
|
||||
});
|
||||
};
|
||||
|
||||
// Lazy chunks mount after show=true — watch subtree + retry briefly
|
||||
markVisible();
|
||||
const mo = new MutationObserver(markVisible);
|
||||
mo.observe(root, { childList: true, subtree: true });
|
||||
const timers = [50, 200, 600, 1500].map((ms) => window.setTimeout(markVisible, ms));
|
||||
|
||||
return () => {
|
||||
mo.disconnect();
|
||||
timers.forEach(clearTimeout);
|
||||
};
|
||||
}, [show]);
|
||||
|
||||
return (
|
||||
|
||||
Loading…
Reference in New Issue
Block a user