@@ -144,13 +144,14 @@ const BuildsTable = () => {
144144 } )
145145 } , [ builds , runningStatusesData ] )
146146
147- // virtualization - account for loader rows only when loading
148- const showPreviousLoader = isFetchingPreviousPage
149- const showNextLoader = isFetchingNextPage
147+ // virtualization - always include placeholder rows when more pages exist
148+ // this ensures scroll position stays stable when new data loads
149+ const hasPreviousRow = hasPreviousPage
150+ const hasNextRow = hasNextPage
150151 const rowCount =
151152 buildsWithLiveStatus . length +
152- ( showPreviousLoader ? 1 : 0 ) +
153- ( showNextLoader ? 1 : 0 )
153+ ( hasPreviousRow ? 1 : 0 ) +
154+ ( hasNextRow ? 1 : 0 )
154155
155156 const virtualizer = useVirtualizer ( {
156157 count : rowCount ,
@@ -168,18 +169,16 @@ const BuildsTable = () => {
168169 ( virtualRows [ virtualRows . length - 1 ] ?. end ?? 0 )
169170 : 0
170171
171- // auto-fetch when scrolling near edges
172+ // auto-fetch when scrolling near edges (when placeholder row becomes visible)
172173 useEffect ( ( ) => {
173174 if ( ! hasNextPage || isFetchingNextPage ) return
174175
175176 const lastVirtualRow = virtualRows [ virtualRows . length - 1 ]
176177 if ( ! lastVirtualRow ) return
177178
178- const lastDataIndex = showPreviousLoader
179- ? lastVirtualRow . index - 1
180- : lastVirtualRow . index
181-
182- if ( lastDataIndex >= buildsWithLiveStatus . length - 1 ) {
179+ // check if the "load more" placeholder row is visible
180+ const loadMoreRowIndex = buildsWithLiveStatus . length + ( hasPreviousRow ? 1 : 0 )
181+ if ( lastVirtualRow . index >= loadMoreRowIndex ) {
183182 fetchNextPage ( )
184183 }
185184 } , [
@@ -188,7 +187,7 @@ const BuildsTable = () => {
188187 isFetchingNextPage ,
189188 buildsWithLiveStatus . length ,
190189 fetchNextPage ,
191- showPreviousLoader ,
190+ hasPreviousRow ,
192191 ] )
193192
194193 useEffect ( ( ) => {
@@ -197,19 +196,15 @@ const BuildsTable = () => {
197196 const firstVirtualRow = virtualRows [ 0 ]
198197 if ( ! firstVirtualRow ) return
199198
200- const firstDataIndex = showPreviousLoader
201- ? firstVirtualRow . index - 1
202- : firstVirtualRow . index
203-
204- if ( firstDataIndex <= 0 ) {
199+ // check if the "load previous" placeholder row is visible (index 0)
200+ if ( firstVirtualRow . index === 0 ) {
205201 fetchPreviousPage ( )
206202 }
207203 } , [
208204 virtualRows ,
209205 hasPreviousPage ,
210206 isFetchingPreviousPage ,
211207 fetchPreviousPage ,
212- showPreviousLoader ,
213208 ] )
214209
215210 // UI state
@@ -279,31 +274,54 @@ const BuildsTable = () => {
279274 ) }
280275
281276 { virtualRows . map ( ( virtualRow ) => {
282- const isPreviousLoaderRow =
283- showPreviousLoader && virtualRow . index === 0
284- const isNextLoaderRow =
285- showNextLoader &&
277+ const isPreviousPlaceholder =
278+ hasPreviousRow && virtualRow . index === 0
279+ const isNextPlaceholder =
280+ hasNextRow &&
286281 virtualRow . index ===
287- buildsWithLiveStatus . length + ( showPreviousLoader ? 1 : 0 )
288- const buildIndex = showPreviousLoader
282+ buildsWithLiveStatus . length + ( hasPreviousRow ? 1 : 0 )
283+ const buildIndex = hasPreviousRow
289284 ? virtualRow . index - 1
290285 : virtualRow . index
291286 const build = buildsWithLiveStatus [ buildIndex ]
292287
293- if ( isPreviousLoaderRow || isNextLoaderRow ) {
288+ if ( isPreviousPlaceholder ) {
289+ return (
290+ < TableRow
291+ key = "placeholder-prev"
292+ style = { { height : ROW_HEIGHT } }
293+ >
294+ < TableCell
295+ colSpan = { 6 }
296+ className = "text-start text-fg-tertiary"
297+ >
298+ { isFetchingPreviousPage && (
299+ < span className = "flex items-center gap-2" >
300+ < Loader variant = "slash" size = "sm" />
301+ Loading...
302+ </ span >
303+ ) }
304+ </ TableCell >
305+ </ TableRow >
306+ )
307+ }
308+
309+ if ( isNextPlaceholder ) {
294310 return (
295311 < TableRow
296- key = { isPreviousLoaderRow ? 'loader-prev' : 'loader- next' }
312+ key = "placeholder- next"
297313 style = { { height : ROW_HEIGHT } }
298314 >
299315 < TableCell
300316 colSpan = { 6 }
301317 className = "text-start text-fg-tertiary"
302318 >
303- < span className = "flex items-center gap-2" >
304- < Loader variant = "slash" size = "sm" />
305- Loading...
306- </ span >
319+ { isFetchingNextPage && (
320+ < span className = "flex items-center gap-2" >
321+ < Loader variant = "slash" size = "sm" />
322+ Loading...
323+ </ span >
324+ ) }
307325 </ TableCell >
308326 </ TableRow >
309327 )
0 commit comments