Skip to content

Commit aa8b0f8

Browse files
committed
scroll state
1 parent 58a7304 commit aa8b0f8

File tree

1 file changed

+26
-31
lines changed

1 file changed

+26
-31
lines changed

public/sidebar-scroll.js

Lines changed: 26 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,43 @@
11
(() => {
2-
const desktopQuery = '(min-width: 50em)';
2+
const ACTIVE_SELECTOR = "[data-starlight-sidebar] a[aria-current='page']";
33

4-
const isDesktopSidebar = () => matchMedia(desktopQuery).matches;
4+
const scrollActiveLink = (behavior = 'auto') => {
5+
const activeLink = document.querySelector(ACTIVE_SELECTOR);
6+
if (!activeLink || typeof activeLink.scrollIntoView !== 'function') return false;
7+
8+
const sidebar = activeLink.closest('[data-starlight-sidebar]');
9+
if (!sidebar) return false;
510

6-
const isActiveLinkVisible = (sidebar, activeLink) => {
711
const sidebarRect = sidebar.getBoundingClientRect();
812
const linkRect = activeLink.getBoundingClientRect();
13+
const isVisible = linkRect.top >= sidebarRect.top && linkRect.bottom <= sidebarRect.bottom;
914

10-
return linkRect.top >= sidebarRect.top && linkRect.bottom <= sidebarRect.bottom;
11-
};
12-
13-
const centerLinkInSidebar = () => {
14-
const sidebar = document.getElementById('starlight__sidebar');
15-
if (!sidebar || !isDesktopSidebar()) return true;
15+
if (!isVisible) {
16+
activeLink.scrollIntoView({ block: 'center', inline: 'nearest', behavior });
17+
}
1618

17-
const activeLink = sidebar.querySelector("a[aria-current='page']");
18-
if (!activeLink) return false;
19+
return true;
20+
};
1921

20-
if (isActiveLinkVisible(sidebar, activeLink)) return true;
22+
const runWhenReady = () => {
23+
if (scrollActiveLink('smooth')) return;
2124

22-
const sidebarRect = sidebar.getBoundingClientRect();
23-
const linkRect = activeLink.getBoundingClientRect();
24-
const linkOffset = linkRect.top - sidebarRect.top + sidebar.scrollTop;
25-
const targetTop = Math.max(linkOffset - sidebar.clientHeight / 2 + linkRect.height / 2, 0);
25+
const sidebar = document.querySelector('[data-starlight-sidebar]') || document.body;
26+
const observer = new MutationObserver(() => {
27+
if (scrollActiveLink('smooth')) observer.disconnect();
28+
});
2629

27-
sidebar.scrollTo({ top: targetTop, behavior: 'auto' });
28-
return true;
30+
observer.observe(sidebar, { childList: true, subtree: true });
2931
};
3032

31-
const scheduleScroll = () => {
32-
if (document.readyState === 'complete' || document.readyState === 'interactive') {
33-
requestAnimationFrame(() => {
34-
if (!centerLinkInSidebar()) {
35-
const sidebar = document.getElementById('starlight__sidebar') || document.body;
36-
const observer = new MutationObserver(() => {
37-
if (centerLinkInSidebar()) observer.disconnect();
38-
});
39-
observer.observe(sidebar, { childList: true, subtree: true });
40-
}
41-
});
33+
const schedule = () => {
34+
if (document.readyState === 'loading') {
35+
document.addEventListener('DOMContentLoaded', runWhenReady, { once: true });
4236
} else {
43-
window.addEventListener('DOMContentLoaded', scheduleScroll, { once: true });
37+
runWhenReady();
4438
}
4539
};
4640

47-
scheduleScroll();
41+
schedule();
42+
window.addEventListener('astro:after-swap', schedule);
4843
})();

0 commit comments

Comments
 (0)