@@ -6,6 +6,7 @@ import type { LocalMessage } from 'stream-chat';
66export type ContainerMeasures = {
77 offsetHeight : number ;
88 scrollHeight : number ;
9+ scrollTop : number ;
910} ;
1011
1112export type UseMessageListScrollManagerParams = {
@@ -101,6 +102,7 @@ export function useMessageListScrollManager(params: UseMessageListScrollManagerP
101102 const measures = useRef < ContainerMeasures > ( {
102103 offsetHeight : 0 ,
103104 scrollHeight : 0 ,
105+ scrollTop : 0 ,
104106 } ) ;
105107 const messages = useRef < LocalMessage [ ] > ( undefined ) ;
106108 const olderPaginationState = useRef < OlderPaginationState > ( {
@@ -130,16 +132,32 @@ export function useMessageListScrollManager(params: UseMessageListScrollManagerP
130132 const finishedLoadingOlder = ! loadingMore && previousLoadingMoreRef . current ;
131133
132134 if ( startedLoadingOlder ) {
135+ // Read the live DOM scroll position instead of the cached ref so we get
136+ // the correct value even when scrollToBottom() has been called but the
137+ // async scroll event hasn't updated the ref yet (common on initial mount).
138+ const liveMeasures = scrollContainerMeasures ( ) ;
139+ const hasOverflow = liveMeasures . scrollHeight > liveMeasures . offsetHeight ;
140+ const liveScrollTop = liveMeasures . scrollTop ;
141+
133142 // Older-page pagination uses one of three modes:
134143 // - `stick-to-top`: user hit the absolute top and wants to keep reading upward
135144 // - `preserve-anchor`: user was only near the top, so keep the same message in view
136145 // - `idle`: no restoration needed for this load cycle
137- if ( scrollTop . current <= 1 ) {
146+ //
147+ // When the container doesn't overflow yet (e.g. content hasn't reached its
148+ // final height due to font loading) the scroll position is meaningless, so
149+ // default to idle to avoid a false stick-to-top that would jump the list.
150+ if ( ! hasOverflow ) {
151+ olderPaginationState . current = {
152+ anchor : null ,
153+ mode : 'idle' ,
154+ } ;
155+ } else if ( liveScrollTop <= 1 ) {
138156 olderPaginationState . current = {
139157 anchor : null ,
140158 mode : 'stick-to-top' ,
141159 } ;
142- } else if ( scrollTop . current < loadMoreScrollThreshold ) {
160+ } else if ( liveScrollTop < loadMoreScrollThreshold ) {
143161 const capturedAnchor = captureAnchor ( ) ;
144162 if ( capturedAnchor ) {
145163 olderPaginationState . current = {
0 commit comments