diff --git a/site/src/jsMain/kotlin/DocsPage.kt b/site/src/jsMain/kotlin/DocsPage.kt index eb3bcea..e666815 100644 --- a/site/src/jsMain/kotlin/DocsPage.kt +++ b/site/src/jsMain/kotlin/DocsPage.kt @@ -181,7 +181,7 @@ fun DocsPage( scheduled = false try { val heads = toc.mapNotNull { id -> el.querySelector("#${id.id}") as? HTMLHeadingElement } - val tops = heads.map { it.getBoundingClientRect().top + window.scrollY } + val tops = heads.map { it.getBoundingClientRect().top } val offset = (updateNavbarOffsetVar() + 16).toDouble() val idx = activeIndexForTops(tops, offset) setActiveTocId(if (idx in toc.indices) toc[idx].id else null) diff --git a/site/src/jsMain/kotlin/Main.kt b/site/src/jsMain/kotlin/Main.kt index 6c95513..38a2f53 100644 --- a/site/src/jsMain/kotlin/Main.kt +++ b/site/src/jsMain/kotlin/Main.kt @@ -1024,11 +1024,15 @@ internal fun normalizePath(path: String): String { // If none are above the offset, returns 0. If list is empty, returns 0. fun activeIndexForTops(tops: List, offsetPx: Double): Int { if (tops.isEmpty()) return 0 + var lastAbove = 0 for (i in tops.indices) { - if (tops[i] - offsetPx > 0.0) return i + if (tops[i] <= offsetPx) { + lastAbove = i + } else { + break + } } - // If all headings are above the offset, select the last one - return tops.size - 1 + return lastAbove } fun main() { diff --git a/site/src/jsTest/kotlin/ScrollSpyTest.kt b/site/src/jsTest/kotlin/ScrollSpyTest.kt index 041de4b..ad5f35e 100644 --- a/site/src/jsTest/kotlin/ScrollSpyTest.kt +++ b/site/src/jsTest/kotlin/ScrollSpyTest.kt @@ -28,20 +28,20 @@ class ScrollSpyTest { fun selectsFirstWhenOnlyFirstIsAboveOffset() { val tops = listOf(20.0, 200.0, 800.0) // px from viewport top val idx = activeIndexForTops(tops, offsetPx = 80.0) - assertEquals(1, idx) // 20 <= 80, 200 > 80 -> index 1 (second heading is first below offset) + assertEquals(0, idx) // 20 <= 80 (active), 200 > 80 (stops) -> index 0 } @Test fun selectsLastHeadingAboveOffset() { val tops = listOf(-100.0, 50.0, 70.0) val idx = activeIndexForTops(tops, offsetPx = 80.0) - assertEquals(2, idx) // all three are <= 80 -> last index + assertEquals(2, idx) // all three are <= 80 -> last index 2 } @Test fun stopsBeforeFirstBelowOffset() { val tops = listOf(-200.0, -50.0, 30.0, 150.0, 400.0) val idx = activeIndexForTops(tops, offsetPx = 80.0) - assertEquals(3, idx) // 30 <= 80 qualifies; 150 > 80 stops, so index 3rd (0-based -> 3?) + assertEquals(2, idx) // 30 <= 80 is the last one; 150 > 80 -> index 2 } }