@@ -36,48 +36,40 @@ const tocHeadings = filterTocHeadings(headings);
3636 const tocLinks = document.querySelectorAll('[data-toc-link]');
3737 if (tocLinks.length === 0) return;
3838
39- const headingIds = Array.from(tocLinks).map((link) => {
40- const href = link.getAttribute('href');
41- return href ? href.slice(1) : '';
42- });
43-
44- const headings = headingIds
45- .map((id) => document.getElementById(id))
46- .filter((el): el is HTMLElement => el !== null);
47-
48- if (headings.length === 0) return;
49-
50- const observer = new IntersectionObserver(
51- (entries) => {
52- // Find the first visible heading
53- const visibleEntry = entries.find((entry) => entry.isIntersecting);
39+ function updateFromHash() {
40+ const hash = window.location.hash || '';
41+ tocLinks.forEach((link, index) => {
42+ const href = link.getAttribute('href');
43+ // Match hash, or default to first link if no hash
44+ const isActive = hash ? href === hash : index === 0;
45+ link.setAttribute('aria-current', isActive ? 'true' : 'false');
46+ });
47+ }
5448
55- if (visibleEntry) {
56- const id = visibleEntry.target.id;
49+ // Update on click (immediately, before hash changes)
50+ tocLinks.forEach((link, index) => {
51+ link.addEventListener('click', (e) => {
52+ tocLinks.forEach((l) => l.setAttribute('aria-current', 'false'));
53+ link.setAttribute('aria-current', 'true');
5754
58- // Update aria-current on all links
59- tocLinks.forEach((link) => {
60- const href = link.getAttribute('href');
61- const isActive = href === `#${id}`;
62- link.setAttribute('aria-current', isActive ? 'true' : 'false');
63- });
55+ // First link scrolls to top of page
56+ if (index === 0) {
57+ e.preventDefault();
58+ window.scrollTo({ top: 0, behavior: 'smooth' });
59+ history.pushState(null, '', link.getAttribute('href') || '');
6460 }
65- },
66- {
67- rootMargin: '-80px 0px -70% 0px',
68- threshold: 0,
69- }
70- );
71-
72- headings.forEach((heading) => {
73- observer.observe(heading);
61+ });
7462 });
7563
64+ // Initial state and hash changes
65+ updateFromHash();
66+ window.addEventListener('hashchange', updateFromHash);
67+
7668 // Cleanup on page transitions
7769 document.addEventListener(
7870 'astro:before-swap',
7971 () => {
80- observer.disconnect( );
72+ window.removeEventListener('hashchange', updateFromHash );
8173 },
8274 { once: true }
8375 );
0 commit comments