@@ -102,7 +102,6 @@ const TableOfContents = ({ containerRef, width, collapsed, onToggle, onItemMouse
102102 useEffect ( ( ) => {
103103 if ( ! containerRef ?. current || sections . length === 0 ) return ;
104104
105- const container = containerRef . current ;
106105 let rafId = null ;
107106
108107 const updateActiveSection = ( ) => {
@@ -112,38 +111,33 @@ const TableOfContents = ({ containerRef, width, collapsed, onToggle, onItemMouse
112111 }
113112
114113 rafId = requestAnimationFrame ( ( ) => {
115- const containerRect = container . getBoundingClientRect ( ) ;
116- const containerTop = containerRect . top ;
117- const containerHeight = containerRect . height ;
118-
114+ const viewportHeight = window . innerHeight ;
115+
119116 // Find the first heading that's clearly visible in the viewport
120117 let activeId = null ;
121118 let fallbackId = null ;
122119 let minDistance = Infinity ;
123-
120+
124121 for ( const section of sections ) {
125122 if ( ! section . element ) continue ;
126-
123+
127124 const rect = section . element . getBoundingClientRect ( ) ;
128- const elementTop = rect . top ;
129-
130- // Distance from top of container (negative = above viewport)
131- const distanceFromTop = elementTop - containerTop ;
132-
125+ const distanceFromTop = rect . top ;
126+
133127 // If heading is in the upper portion of viewport (top 60%), make it active
134- if ( distanceFromTop >= 0 && distanceFromTop <= containerHeight * 0.6 ) {
128+ if ( distanceFromTop >= 0 && distanceFromTop <= viewportHeight * 0.6 ) {
135129 activeId = section . id ;
136130 break ; // First one wins - this is a clear active section
137131 }
138-
132+
139133 // Track closest heading for potential fallback, but only if reasonably close
140134 const absoluteDistance = Math . abs ( distanceFromTop ) ;
141- if ( absoluteDistance < minDistance && absoluteDistance < containerHeight * 0.8 ) {
135+ if ( absoluteDistance < minDistance && absoluteDistance < viewportHeight * 0.8 ) {
142136 minDistance = absoluteDistance ;
143137 fallbackId = section . id ;
144138 }
145139 }
146-
140+
147141 // Only update if we found a clearly active section, or if we don't have any active section yet
148142 if ( activeId ) {
149143 // Clear active section found
@@ -158,14 +152,14 @@ const TableOfContents = ({ containerRef, width, collapsed, onToggle, onItemMouse
158152 } ) ;
159153 } ;
160154
161- // Listen to scroll events
162- container . addEventListener ( 'scroll' , updateActiveSection , { passive : true } ) ;
163-
155+ // Listen to scroll events on window (page uses window scrolling, not container scrolling)
156+ window . addEventListener ( 'scroll' , updateActiveSection , { passive : true } ) ;
157+
164158 // Initial update
165159 updateActiveSection ( ) ;
166160
167161 return ( ) => {
168- container . removeEventListener ( 'scroll' , updateActiveSection ) ;
162+ window . removeEventListener ( 'scroll' , updateActiveSection ) ;
169163 if ( rafId ) {
170164 cancelAnimationFrame ( rafId ) ;
171165 }
0 commit comments