diff --git a/webview-ui/src/components/chat/ChatView.tsx b/webview-ui/src/components/chat/ChatView.tsx index 9b8c96dea1..3ecf39dfa6 100644 --- a/webview-ui/src/components/chat/ChatView.tsx +++ b/webview-ui/src/components/chat/ChatView.tsx @@ -1377,20 +1377,31 @@ const ChatViewComponent: React.ForwardRefRenderFunction { + // Only auto-scroll if we're supposed to be following the conversation if (!disableAutoScrollRef.current) { if (isTaller) { scrollToBottomSmooth() } else { setTimeout(() => scrollToBottomAuto(), 0) } + } else if (isAtBottom) { + // If auto-scroll is disabled but we're at the bottom, + // the user likely wants to follow along, so scroll anyway + if (isTaller) { + scrollToBottomSmooth() + } else { + setTimeout(() => scrollToBottomAuto(), 0) + } } }, - [scrollToBottomSmooth, scrollToBottomAuto], + [scrollToBottomSmooth, scrollToBottomAuto, isAtBottom], ) useEffect(() => { let timer: ReturnType | undefined - if (!disableAutoScrollRef.current) { + // Auto-scroll on new messages if auto-scroll is enabled OR if we're at the bottom + // This ensures we follow the conversation when the user is actively reading at the bottom + if (!disableAutoScrollRef.current || isAtBottom) { timer = setTimeout(() => scrollToBottomSmooth(), 50) } return () => { @@ -1398,18 +1409,27 @@ const ChatViewComponent: React.ForwardRefRenderFunction { - const wheelEvent = event as WheelEvent + const handleWheel = useCallback( + (event: Event) => { + const wheelEvent = event as WheelEvent - if (wheelEvent.deltaY && wheelEvent.deltaY < 0) { - if (scrollContainerRef.current?.contains(wheelEvent.target as Node)) { - // User scrolled up - disableAutoScrollRef.current = true + if (wheelEvent.deltaY) { + if (scrollContainerRef.current?.contains(wheelEvent.target as Node)) { + if (wheelEvent.deltaY < 0) { + // User scrolled up - disable auto-scroll + disableAutoScrollRef.current = true + } else if (wheelEvent.deltaY > 0 && isAtBottom) { + // User scrolled down and we're at bottom - re-enable auto-scroll + // This helps when user scrolls down to catch up with messages + disableAutoScrollRef.current = false + } + } } - } - }, []) + }, + [isAtBottom], + ) useEvent("wheel", handleWheel, window, { passive: true }) // passive improves scrolling performance @@ -1876,11 +1896,14 @@ const ChatViewComponent: React.ForwardRefRenderFunction { setIsAtBottom(isAtBottom) if (isAtBottom) { + // Re-enable auto-scroll when we reach the bottom disableAutoScrollRef.current = false } + // Show scroll-to-bottom button only when auto-scroll is disabled and not at bottom setShowScrollToBottom(disableAutoScrollRef.current && !isAtBottom) }} - atBottomThreshold={10} + // Increase threshold to be more forgiving about what counts as "at bottom" + atBottomThreshold={50} initialTopMostItemIndex={groupedMessages.length - 1} />