|
6 | 6 |
|
7 | 7 | let headings: NodeListOf<HTMLHeadingElement>;
|
8 | 8 | let current = $state('');
|
| 9 | + let locked = $state(false); |
9 | 10 |
|
10 | 11 | afterNavigate(() => {
|
11 |
| - current = location.hash.slice(1); |
12 | 12 | headings = content.querySelectorAll('h2');
|
13 |
| - update(); // Ensure active link is set correctly on navigation |
| 13 | + for (const heading of headings) { |
| 14 | + const anchor = heading.querySelector('a'); |
| 15 | + if (anchor) anchor.onclick = onclick; |
| 16 | + } |
| 17 | + onclick(); |
14 | 18 | });
|
15 | 19 |
|
16 |
| - // Update function to activate the correct section link |
17 |
| - function update() { |
| 20 | + function onclick() { |
| 21 | + current = location.hash.slice(1); |
| 22 | + // avoid onscroll handler from inaccurately updating |
| 23 | + locked = true; |
| 24 | + setTimeout(() => (locked = false), 100); |
| 25 | + } |
| 26 | +
|
| 27 | + function onscroll() { |
| 28 | + if (locked) return; |
| 29 | +
|
18 | 30 | const threshold = (innerHeight * 1) / 3;
|
19 |
| - let found = false; |
20 | 31 |
|
21 | 32 | for (let i = 0; i < headings.length; i++) {
|
22 | 33 | const heading = headings[i];
|
|
28 | 39 | (!next || next.getBoundingClientRect().top > threshold)
|
29 | 40 | ) {
|
30 | 41 | current = heading.id;
|
31 |
| - found = true; |
32 | 42 | break;
|
33 | 43 | }
|
34 | 44 | }
|
35 | 45 |
|
36 | 46 | // Handle case when scrolled to the top of the page
|
37 |
| - if (!found && scrollY === 0) { |
| 47 | + if (scrollY === 0) { |
38 | 48 | current = '';
|
39 | 49 | }
|
40 | 50 | }
|
41 | 51 | </script>
|
42 | 52 |
|
43 |
| -<svelte:window onscroll={update} onhashchange={() => (current = location.hash.slice(1))} /> |
| 53 | +<svelte:window {onscroll} onhashchange={onclick} /> |
44 | 54 |
|
45 | 55 | <aside class="on-this-page">
|
46 | 56 | <label>
|
|
51 | 61 | <nav>
|
52 | 62 | <ul>
|
53 | 63 | <li>
|
54 |
| - <a href="/{document.slug}" class:active={current === ''}> |
| 64 | + <a href="/{document.slug}" class:active={current === ''} {onclick}> |
55 | 65 | {document.metadata.title}
|
56 | 66 | </a>
|
57 | 67 | </li>
|
58 | 68 |
|
59 | 69 | {#each document.sections as section}
|
60 | 70 | <li>
|
61 |
| - <a href="#{section.slug}" class:active={current === section.slug}>{@html section.title}</a |
| 71 | + <a href="#{section.slug}" class:active={current === section.slug} {onclick} |
| 72 | + >{@html section.title}</a |
62 | 73 | >
|
63 | 74 | </li>
|
64 | 75 | {/each}
|
|
0 commit comments