|
| 1 | +--- |
| 2 | +import Default from "@astrojs/starlight/components/Sidebar.astro"; |
| 3 | +import type { Props } from "@astrojs/starlight/props"; |
| 4 | +
|
| 5 | +const props = Astro.props as Props; |
| 6 | +--- |
| 7 | + |
| 8 | +<div data-ecency-sidebar> |
| 9 | + <Default {...props}> |
| 10 | + <slot /> |
| 11 | + </Default> |
| 12 | +</div> |
| 13 | + |
| 14 | +<script client:load> |
| 15 | + const ACTIVE_SELECTOR = "[data-ecency-sidebar] a[aria-current='page']"; |
| 16 | + |
| 17 | + const prefersReducedMotion = window.matchMedia?.( |
| 18 | + "(prefers-reduced-motion: reduce)" |
| 19 | + ).matches; |
| 20 | + |
| 21 | + const scrollActiveLink = (behavior = "auto") => { |
| 22 | + const activeLink = document.querySelector(ACTIVE_SELECTOR); |
| 23 | + if (!activeLink || typeof activeLink.scrollIntoView !== "function") return; |
| 24 | + |
| 25 | + // Scroll the active link into the center of the sidebar |
| 26 | + activeLink.scrollIntoView({ |
| 27 | + block: "center", |
| 28 | + inline: "nearest", |
| 29 | + behavior: prefersReducedMotion ? "auto" : behavior, |
| 30 | + }); |
| 31 | + }; |
| 32 | + |
| 33 | + const run = () => { |
| 34 | + // initial attempt |
| 35 | + scrollActiveLink("smooth"); |
| 36 | + |
| 37 | + // if you want to be extra-safe with late-rendered content, you could |
| 38 | + // wrap in a small timeout, but often not needed: |
| 39 | + // setTimeout(() => scrollActiveLink("smooth"), 0); |
| 40 | + }; |
| 41 | + |
| 42 | + if (document.readyState === "loading") { |
| 43 | + document.addEventListener("DOMContentLoaded", run, { once: true }); |
| 44 | + } else { |
| 45 | + run(); |
| 46 | + } |
| 47 | + |
| 48 | + // Handle Astro/Starlight client-side navigation |
| 49 | + window.addEventListener("astro:after-swap", () => { |
| 50 | + // no animation on fast internal nav if you prefer: |
| 51 | + scrollActiveLink("auto"); |
| 52 | + }); |
| 53 | +</script> |
0 commit comments