Fixing scrolling behavior in the chat panel (#2040)
closes #2038 #2055
<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Fixes chat panel scrolling (issue #2038). Auto-scroll only runs while
streaming and when you’re near the bottom, and a “scroll to bottom”
button appears when you scroll away.
- **Bug Fixes**
- Use Virtuoso scrollerRef and a conditional followOutput to control
auto-scroll based on streaming state and distance from bottom.
- Track distance and user scrolling to show/hide the button; clean up
listeners on unmount.
- Add overflow-y-auto to the messages list and a test-mode fallback that
uses the container’s scroll events.
<sup>Written for commit 2307453c7f1ad721d6eca9cfc5a9a24224f5da26.
Summary will update on new commits.</sup>
<!-- End of auto-generated description by cubic. -->
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
Replaced custom scroll tracking logic with Virtuoso's native scroll
state management to fix the issue where users couldn't scroll up during
streaming.
**Key Changes:**
- Removed manual scroll event listeners, timeout refs, and distance
calculations from `ChatPanel.tsx`
- Delegated scroll state to Virtuoso's `atBottomStateChange` callback
which detects when user is within 150px of bottom
- Converted `followOutput` from always `"smooth"` to a function that
returns `"smooth"` only when `isStreaming && isAtBottom`, otherwise
returns `false` to prevent forced scrolling
- This allows users to scroll up and read earlier messages while the AI
generates a response, restoring the behavior that existed before PR
#1993
<h3>Confidence Score: 5/5</h3>
- This PR is safe to merge with minimal risk
- The changes are well-architected and leverage Virtuoso's built-in
functionality instead of reinventing scroll tracking logic. The fix
directly addresses the reported issue by making `followOutput`
conditional on user position, which is the correct approach for this
library.
- No files require special attention
<h3>Important Files Changed</h3>
| Filename | Overview |
|----------|----------|
| src/components/ChatPanel.tsx | Refactored scroll handling to delegate
to Virtuoso's native `atBottomStateChange`, removed custom scroll
tracking logic and manual scroll event listeners |
| src/components/chat/MessagesList.tsx | Added `atBottomStateChange` and
conditional `followOutput` to Virtuoso, allowing users to scroll up
while streaming without forced auto-scroll |
</details>
<h3>Sequence Diagram</h3>
```mermaid
sequenceDiagram
participant User
participant ChatPanel
participant MessagesList
participant Virtuoso
Note over User,Virtuoso: Streaming Scenario
User->>MessagesList: Scrolls to read earlier messages
Virtuoso->>Virtuoso: Detects scroll position > 150px from bottom
Virtuoso->>MessagesList: atBottomStateChange(false)
MessagesList->>ChatPanel: onScrollStateChange(false)
ChatPanel->>ChatPanel: setShowScrollButton(true)
Note over Virtuoso: New message chunk arrives
Virtuoso->>Virtuoso: followOutput((isAtBottom) => isAtBottom && isStreaming ? "smooth" : false)
Virtuoso->>Virtuoso: Returns false (user scrolled away)
Virtuoso->>Virtuoso: Does NOT auto-scroll
Note over User,Virtuoso: User Returns to Bottom
User->>ChatPanel: Clicks scroll-to-bottom button
ChatPanel->>MessagesList: scrollToBottom("smooth")
MessagesList->>Virtuoso: scrollIntoView on messagesEndRef
Virtuoso->>Virtuoso: Scrolls to bottom
Virtuoso->>MessagesList: atBottomStateChange(true)
MessagesList->>ChatPanel: onScrollStateChange(true)
ChatPanel->>ChatPanel: setShowScrollButton(false)
Note over Virtuoso: Subsequent message chunks
Virtuoso->>Virtuoso: followOutput returns "smooth" (isAtBottom = true)
Virtuoso->>Virtuoso: Auto-scrolls smoothly
```
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Improves chat scrolling reliability across production (Virtuoso) and
test modes.
>
> - Integrates `MessagesList` with Virtuoso `scrollerRef` and
conditional `followOutput` (auto-scroll only when `isStreaming` and
within ~280px of bottom), with proper listener cleanup
> - Centralizes scroll tracking in `ChatPanel` using
`distanceFromBottomRef` and a timeout to debounce user scrolling;
toggles a "scroll to bottom" button when scrolled away
> - Adds test-mode behavior: non-virtualized rendering, container scroll
listeners, and manual auto-scroll near bottom
> - Ensures smooth scroll-to-bottom after streaming completes; applies
`overflow-y-auto` and passes new props (`onScrollerRef`,
`distanceFromBottomRef`, `isUserScrolling`) between components
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
2307453c7f1ad721d6eca9cfc5a9a24224f5da26. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
正在显示
请
注册
或者
登录
后发表评论