From 47a17b172925899c117827719546b4b99ae417c1 Mon Sep 17 00:00:00 2001 From: Bramus Date: Wed, 4 Dec 2024 15:27:49 +0100 Subject: [PATCH] Use an IntersectionObserver based ScrollSpy in browsers with no SDA support --- src/components/nav.aside.astro | 66 ++++++++++++++++++++++++++++------ 1 file changed, 55 insertions(+), 11 deletions(-) diff --git a/src/components/nav.aside.astro b/src/components/nav.aside.astro index af1b46d..670519e 100644 --- a/src/components/nav.aside.astro +++ b/src/components/nav.aside.astro @@ -107,13 +107,11 @@ const { biomes } = Astro.props; e.target.lastScrollTop = st <= 0 ? 0 : st; } - const observer = new IntersectionObserver( + const biomeObserver = new IntersectionObserver( (entries) => { entries.forEach((entry) => { if (entry.isIntersecting) { - const details = document.querySelector( - `#${entry.target.getAttribute("data-details-target")}` - ); + const details = document.querySelector(`#${entry.target.getAttribute("data-details-target")}`); details.setAttribute("open", ""); } }); @@ -123,15 +121,49 @@ const { biomes } = Astro.props; } ); + const featureObserver = new IntersectionObserver( + (entries) => { + entries.forEach((entry) => { + const id = entry.target.getAttribute("id"); + const $li = document.querySelector(`aside nav details li:has(a[href="#${id}"])`); + + if (!$li) return; + + if (entry.isIntersecting) { + $li.classList.add('in-view'); + } else { + $li.classList.remove('in-view'); + } + }); + }, + { + threshold: 0, + } + ); + function observeForSidenav() { document.querySelectorAll(".biome > section").forEach((biome) => { - observer.observe(biome); + biomeObserver.observe(biome); + + if (!CSS.supports('animation-timeline: view()')) { + const features = biome.querySelectorAll('.features-list > div > article'); + features.forEach(feature => { + featureObserver.observe(feature); + }); + } }); } function unobserveForSidenav() { document.querySelectorAll(".biome > section").forEach((biome) => { - observer.unobserve(biome); + biomeObserver.unobserve(biome); + + if (!CSS.supports('animation-timeline: view()')) { + const features = biome.querySelectorAll('.features-list > div > article'); + features.forEach(feature => { + featureObserver.unobserve(feature); + }); + } }); } @@ -246,14 +278,26 @@ const { biomes } = Astro.props; position: absolute; top: 0; left: 4px; - background: var(--link); - + inline-size: 3px; block-size: 100%; + + /* SDA ScrollSpy */ + @supports (animation-timeline: view()) { + background: var(--link); + transform: scaleY(0); + animation: i-spy linear; + animation-timeline: var(--_view-timeline); + } + + @supports not (animation-timeline: view()) { + background: transparent; + } + } - transform: scaleY(0); - animation: i-spy linear; - animation-timeline: var(--_view-timeline); + /* IntersectionObserver-based ScrollSpy */ + &.in-view::before { + background: var(--link); } & code {