diff --git a/src/globals.css b/src/globals.css index 670c714..7d3c4f1 100644 --- a/src/globals.css +++ b/src/globals.css @@ -156,6 +156,12 @@ z-index: 10000; } +/* Allow to scroll past the last section, needed for fragment-directed navigation. */ +section#contact { + min-height: 100vh; +} + +/* Fix scrolling to section by fragment, making sure it shows in the right spot and not behind the navbar. */ section { scroll-margin-top: calc(var(--spacing) * 16 + var(--spacing) * 4); -} +} \ No newline at end of file diff --git a/src/hooks/color-sections.tsx b/src/hooks/color-sections.tsx index beab322..0ce6d88 100644 --- a/src/hooks/color-sections.tsx +++ b/src/hooks/color-sections.tsx @@ -6,7 +6,7 @@ export const linksOrder: Array = [ "tickets", "cfp", "details", - "contact" + "contact", ] export function useColorSections(parent: React.RefObject) { @@ -27,6 +27,7 @@ export function useColorSections(parent: React.RefObject) acc[value] = parent.current!.querySelector('[data-sub="' + value + '"]')!; return acc; }, {} as Record); + console.log(subs); const links = linksOrder.reduce((acc, value) => { acc[value] = parent.current!.querySelector('[href="#' + value + '"]')!; return acc; @@ -34,22 +35,32 @@ export function useColorSections(parent: React.RefObject) console.log(links) - const observer = new IntersectionObserver((entries) => { + // Set of currently intersecting sections by ID. + let intersecting: Set = new Set; + const observer = new IntersectionObserver((entries) => { + // Update intersection set based on diff. + let startedIntersecting: Set = new Set; + let stoppedIntersecting: Set = new Set; for (const entry of entries) { - const target = entry.target.id as Sections if (entry.isIntersecting) { - // FIXME: This seems to be VERY broken on firefox. - // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1250972 - // It basically spikes up CPU usage to some enormous values just to update the hash, like WTF firefox. - // if (history.replaceState) { - // timeout = setTimeout(() => { - // history.replaceState(null, "", `#${target}`) - // }, 150) - // } + startedIntersecting.add(entry.target.id); + } else { + stoppedIntersecting.add(entry.target.id); + } + } + intersecting = intersecting.difference(stoppedIntersecting); + intersecting = intersecting.union(startedIntersecting); + console.log(intersecting); + + // Act upon intersection set to find the highest intersecting section - + // that's our 'active' section. + for (const id of linksOrder) { + if (intersecting.has(id)) { + console.log("best: " + id); subs[previous.current]?.classList.remove('scale-x-100'); links[previous.current]?.classList.remove('text-primary'); - previous.current = target; + previous.current = id; subs[previous.current]?.classList.add('scale-x-100'); links[previous.current]?.classList.add('text-primary');