Build the full site from the copy decks
Adds About, Contact, Services (index + 8) and Industries (index + 7), generated from structured JSON converted out of the .docx copy decks by scripts/convert-docs.py. Shared header with dropdowns, footer, contact form (mailto until a backend exists), FAQ/breadcrumb JSON-LD, sitemap and robots. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -2,23 +2,48 @@
|
||||
|
||||
import { useEffect } from "react";
|
||||
|
||||
/** Adds `is-in` to every `[data-reveal]` / `[data-reveal-group]` element as it scrolls into view. */
|
||||
const SELECTOR = "[data-reveal], [data-reveal-group]";
|
||||
|
||||
/**
|
||||
* Marks `[data-reveal]` / `[data-reveal-group]` elements with `data-in` as they scroll into view.
|
||||
* Render it as the last child of a page: its effect then runs only after the page's markup has
|
||||
* hydrated, so touching those elements can't cause a hydration mismatch.
|
||||
*/
|
||||
export default function RevealObserver() {
|
||||
useEffect(() => {
|
||||
const targets = document.querySelectorAll<HTMLElement>("[data-reveal], [data-reveal-group]");
|
||||
const io = new IntersectionObserver(
|
||||
(entries) => {
|
||||
for (const entry of entries) {
|
||||
if (entry.isIntersecting) {
|
||||
entry.target.classList.add("is-in");
|
||||
(entry.target as HTMLElement).dataset.in = "";
|
||||
io.unobserve(entry.target);
|
||||
}
|
||||
}
|
||||
},
|
||||
{ rootMargin: "0px 0px -12% 0px", threshold: 0.12 },
|
||||
);
|
||||
targets.forEach((el) => io.observe(el));
|
||||
return () => io.disconnect();
|
||||
const watch = (root: ParentNode) =>
|
||||
root.querySelectorAll<HTMLElement>(SELECTOR).forEach((el) => {
|
||||
if (!("in" in el.dataset)) io.observe(el);
|
||||
});
|
||||
|
||||
watch(document);
|
||||
const mo = new MutationObserver((records) => {
|
||||
for (const r of records) {
|
||||
r.addedNodes.forEach((n) => {
|
||||
if (n instanceof HTMLElement) {
|
||||
if (n.matches(SELECTOR) && !("in" in n.dataset)) io.observe(n);
|
||||
watch(n);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
mo.observe(document.body, { childList: true, subtree: true });
|
||||
|
||||
return () => {
|
||||
io.disconnect();
|
||||
mo.disconnect();
|
||||
};
|
||||
}, []);
|
||||
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user