summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Swithinbank2023-05-17 13:43:35 +0200
committerGitHub2023-05-17 13:43:35 +0200
commit4460e55de210fd9a23a762fe76f5c32297d68d76 (patch)
tree876f8e5375b52c6bde8ab0ffabc6c467a42c2d4c
parenta91191e8308ffa746a3eadeea61e39412f32f926 (diff)
downloadIT.starlight-4460e55de210fd9a23a762fe76f5c32297d68d76.tar.gz
IT.starlight-4460e55de210fd9a23a762fe76f5c32297d68d76.tar.bz2
IT.starlight-4460e55de210fd9a23a762fe76f5c32297d68d76.zip
Improve table of contents intersection observer (#64)
-rw-r--r--.changeset/grumpy-trains-decide.md5
-rw-r--r--packages/starlight/components/TableOfContents/MobileTableOfContents.astro2
-rw-r--r--packages/starlight/components/TableOfContents/starlight-toc.ts30
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);
+ });
}
}