diff options
author | Chris Swithinbank | 2023-05-17 13:43:35 +0200 |
---|---|---|
committer | GitHub | 2023-05-17 13:43:35 +0200 |
commit | 4460e55de210fd9a23a762fe76f5c32297d68d76 (patch) | |
tree | 876f8e5375b52c6bde8ab0ffabc6c467a42c2d4c | |
parent | a91191e8308ffa746a3eadeea61e39412f32f926 (diff) | |
download | IT.starlight-4460e55de210fd9a23a762fe76f5c32297d68d76.tar.gz IT.starlight-4460e55de210fd9a23a762fe76f5c32297d68d76.tar.bz2 IT.starlight-4460e55de210fd9a23a762fe76f5c32297d68d76.zip |
Improve table of contents intersection observer (#64)
3 files changed, 30 insertions, 7 deletions
diff --git a/.changeset/grumpy-trains-decide.md b/.changeset/grumpy-trains-decide.md new file mode 100644 index 00000000..72ca0b6d --- /dev/null +++ b/.changeset/grumpy-trains-decide.md @@ -0,0 +1,5 @@ +--- +"@astrojs/starlight": patch +--- + +Fix table of contents intersection observer for all possible viewport sizes. diff --git a/packages/starlight/components/TableOfContents/MobileTableOfContents.astro b/packages/starlight/components/TableOfContents/MobileTableOfContents.astro index 9cb36c6e..14efd35c 100644 --- a/packages/starlight/components/TableOfContents/MobileTableOfContents.astro +++ b/packages/starlight/components/TableOfContents/MobileTableOfContents.astro @@ -121,7 +121,7 @@ const toc = generateToC(Astro.props.headings, config.tableOfContents); } constructor() { - super(); + super({ smallViewport: true }); const details = this.querySelector('details'); if (!details) return; const closeToC = () => { diff --git a/packages/starlight/components/TableOfContents/starlight-toc.ts b/packages/starlight/components/TableOfContents/starlight-toc.ts index fd194450..5320b8d8 100644 --- a/packages/starlight/components/TableOfContents/starlight-toc.ts +++ b/packages/starlight/components/TableOfContents/starlight-toc.ts @@ -12,7 +12,7 @@ export class StarlightTOC extends HTMLElement { this._current = link; } - constructor() { + constructor({ smallViewport = false } = {}) { super(); /** All the links in the table of contents. */ @@ -68,17 +68,35 @@ export class StarlightTOC extends HTMLElement { } }; - const headingsObserver = new IntersectionObserver(setCurrent, { - rootMargin: '-10% 0% -85%', - }); - // Observe elements with an `id` (most likely headings) and their siblings. // Also observe direct children of `.content` to include elements before // the first heading. const toObserve = document.querySelectorAll( 'main [id], main [id] ~ *, main .content > *' ); - toObserve.forEach((h) => headingsObserver.observe(h)); + /** Start intersections at nav height + 2rem padding. */ + const top = (smallViewport ? 104 : 64) + 32; + /** End intersections 1.5rem later. */ + const bottom = top + 24; + + let observer: IntersectionObserver | undefined; + function observe() { + if (observer) observer.disconnect(); + const height = document.documentElement.clientHeight; + const rootMargin = `-${top}px 0% ${bottom - height}px`; + observer = new IntersectionObserver(setCurrent, { rootMargin }); + toObserve.forEach((h) => observer!.observe(h)); + } + observe(); + + const onIdle = window.requestIdleCallback || ((cb) => setTimeout(cb, 1)); + let timeout: NodeJS.Timeout; + window.addEventListener('resize', () => { + // Disable intersection observer while window is resizing. + if (observer) observer.disconnect(); + clearTimeout(timeout); + timeout = setTimeout(() => onIdle(observe), 200); + }); } } |