@@ -95,13 +95,25 @@ const throttle = (func, delay) => {
9595 }
9696}
9797
98+ // Check if user has scrolled to the bottom of the page
99+ const isAtBottom = () => {
100+ const scrollHeight = document .documentElement .scrollHeight
101+ const scrollTop = document .documentElement .scrollTop || document .body .scrollTop
102+ const clientHeight = document .documentElement .clientHeight
103+ // Consider "at bottom" if within 10% of viewport height from the bottom
104+ // This scales better across different screen sizes
105+ const threshold = clientHeight * 0.1
106+ return scrollHeight - scrollTop - clientHeight < threshold
107+ }
108+
98109// Update sidebar active state based on the topmost visible heading
99110const updateSidebarActiveState = () => {
100111 const sidebar = document .querySelector (' .sidebar' )
101112 if (! sidebar) return
102113
103114 const sidebarAnchors = sidebar .querySelectorAll (' a' )
104115 const sidebarAnchorsContainer = sidebar .querySelectorAll (' .collapsible.sidebar-sub-header' )
116+ const pageAnchors = document .querySelectorAll (' .header-anchor' )
105117
106118 // Get all visible headings sorted by their position (topmost first)
107119 const sortedVisibleHeadings = Array .from (visibleHeadings .value ).sort ((a , b ) => {
@@ -110,12 +122,33 @@ const updateSidebarActiveState = () => {
110122 return aRect .top - bRect .top
111123 })
112124
113- // Select the topmost visible heading
114- const topmostHeading = sortedVisibleHeadings[0 ]
125+ let targetHeading = null
126+
127+ // If at bottom of page, select the last heading that's above the viewport center
128+ if (isAtBottom () && pageAnchors .length > 0 ) {
129+ const viewportCenter = window .innerHeight / 2
130+ const allAnchorsArray = Array .from (pageAnchors)
131+
132+ // Find all headings that are above the viewport center
133+ const headingsAboveCenter = allAnchorsArray .filter (anchor => {
134+ const rect = anchor .getBoundingClientRect ()
135+ return rect .top < viewportCenter
136+ })
137+
138+ // Select the last one (closest to bottom)
139+ if (headingsAboveCenter .length > 0 ) {
140+ targetHeading = headingsAboveCenter[headingsAboveCenter .length - 1 ]
141+ }
142+ }
143+
144+ // If not at bottom or no heading found, use the topmost visible heading
145+ if (! targetHeading && sortedVisibleHeadings .length > 0 ) {
146+ targetHeading = sortedVisibleHeadings[0 ]
147+ }
115148
116- if (! topmostHeading ) return
149+ if (! targetHeading ) return
117150
118- const currentAnchor = topmostHeading .getAttribute (' data-anchor' )
151+ const currentAnchor = targetHeading .getAttribute (' data-anchor' )
119152
120153 // Update active class on sidebar links
121154 sidebarAnchors .forEach (a => a .classList .remove (' active' ))
0 commit comments