fix(#552): release stick-to-bottom on any upward user scroll
The chat viewport previously only released stick-to-bottom when the user scrolled up AND was already more than 200px from the bottom. While reading near the end of a streaming response, any upward scroll inside the bottom 200px did nothing — the ResizeObserver then yanked the viewport back to the bottom on the next streaming chunk, producing the 'can't scroll up' tug-of-war reported in #552. Fix: any user-initiated upward scroll releases stick-to-bottom immediately. Re-stick only when the user has stopped scrolling up AND is at the bottom (<=NEAR_BOTTOM_THRESHOLD). Applied symmetrically in ChatContainerRoot (handleScroll) and in chat-message-list's handleUserScroll mirror.
This commit is contained in:
@@ -48,13 +48,21 @@ function ChatContainerRoot({
|
||||
if (!element) return
|
||||
|
||||
const handleScroll = () => {
|
||||
// Track stick-to-bottom internally based on actual scroll position
|
||||
// Track stick-to-bottom internally based on actual scroll position.
|
||||
// Bug #552: previously we only released stick-to-bottom when the user
|
||||
// both scrolled up AND was already >200px from bottom. That meant any
|
||||
// upward scroll within the bottom 200px did nothing — and during heavy
|
||||
// streaming the ResizeObserver immediately yanked the viewport back to
|
||||
// the bottom on the next content growth, producing the "can't scroll up"
|
||||
// tug-of-war. Fix: ANY user-initiated upward scroll releases stick. Only
|
||||
// re-stick when the user has stopped scrolling up AND is right at the
|
||||
// bottom (≤NEAR_BOTTOM_THRESHOLD).
|
||||
const distFromBottom =
|
||||
element.scrollHeight - element.scrollTop - element.clientHeight
|
||||
const wasScrollingUp = element.scrollTop < lastScrollTopRef.current - 5
|
||||
lastScrollTopRef.current = element.scrollTop
|
||||
|
||||
if (wasScrollingUp && distFromBottom > NEAR_BOTTOM_THRESHOLD) {
|
||||
if (wasScrollingUp) {
|
||||
stickToBottomRef.current = false
|
||||
} else if (distFromBottom <= NEAR_BOTTOM_THRESHOLD) {
|
||||
stickToBottomRef.current = true
|
||||
|
||||
@@ -722,7 +722,11 @@ function ChatMessageListComponent({
|
||||
const wasScrollingUp = metrics.scrollTop < lastScrollTopRef.current - 5
|
||||
lastScrollTopRef.current = metrics.scrollTop
|
||||
|
||||
if (wasScrollingUp && !nearBottom) {
|
||||
// Bug #552: any user-initiated upward scroll releases stick-to-bottom
|
||||
// (previously required >200px from bottom, which let streaming yank the
|
||||
// viewport back down during near-bottom reading). Re-stick only when the
|
||||
// user lands back at the bottom.
|
||||
if (wasScrollingUp) {
|
||||
stickToBottomRef.current = false
|
||||
isNearBottomRef.current = false
|
||||
} else if (nearBottom) {
|
||||
|
||||
Reference in New Issue
Block a user