Skip to content

Conversation

@stevenvo
Copy link
Contributor

Summary

Fixes the annoying behavior where the AI panel continuously auto-scrolls to the bottom while streaming, making it impossible to read earlier parts of long responses.

Problem

When the AI is generating a long response, the panel auto-scrolls to show new content. If you try to scroll up to read something earlier, it immediately scrolls you back down, making it very frustrating to read.

Solution

  • Detects when user manually scrolls up (>50px from bottom)
  • Stops auto-scrolling while user is reading earlier content
  • Resumes auto-scrolling when user scrolls back near the bottom
  • Uses passive event listener for better performance

Test Plan

  • Start AI chat with long response
  • Scroll up while AI is streaming
  • Verify scroll position stays where you scrolled
  • Scroll back to bottom
  • Verify auto-scroll resumes

🤖 Generated with Claude Code

When the AI is streaming responses, the panel would continuously
auto-scroll to the bottom, making it impossible to read earlier parts
of the response.

This change detects when the user has manually scrolled up (more than
50px from bottom) and stops auto-scrolling until they scroll back near
the bottom.

- Add scroll event listener to detect manual user scrolling
- Track userHasScrolledUp state
- Only auto-scroll if user is at/near bottom
- Improves readability of long AI responses

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@CLAassistant
Copy link

CLAassistant commented Dec 15, 2025

CLA assistant check
All committers have signed the CLA.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 15, 2025

Warning

Rate limit exceeded

@stevenvo has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 10 minutes and 23 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between cacd60a and e0f7770.

📒 Files selected for processing (1)
  • frontend/app/aipanel/aipanelmessages.tsx (2 hunks)

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

This change adds user-driven scroll tracking to the AI panel messages component to prevent automatic scrolling when users manually scroll up. It introduces two refs to track scroll state and adds a scroll event listener that detects when the user is more than 50px away from the bottom. Auto-scroll behavior is now conditional on whether the user has scrolled up, affecting triggers on message changes, panel open events, and status changes. The scroll state is reset after auto-scrolling completes.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Scroll event listener performance: Scroll events fire frequently; verify debouncing or throttling is appropriate and doesn't introduce lag
  • Multiple auto-scroll trigger interactions: Review how the userHasScrolledUp flag interacts across different auto-scroll conditions (message changes, panel open, status changes) to ensure no conflicting behaviors
  • Edge cases in scroll detection: Validate the 50px threshold works across different viewport sizes and content scenarios
  • Ref cleanup and lifecycle: Confirm scroll event listeners are properly cleaned up to prevent memory leaks

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and accurately summarizes the main change: preventing auto-scroll when users manually scroll up in the AI panel.
Description check ✅ Passed The description is directly related to the changeset, providing context on the problem being solved and the implemented solution.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +44 to +46
const handleScroll = () => {
// Ignore scroll events triggered by our auto-scroll
if (isAutoScrolling.current) return;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Scroll lock ignored while streaming updates

During streaming, scrollToBottom marks isAutoScrolling true for 100ms on every new message; because this handler exits early when that flag is set, user scroll events occurring while tokens stream faster than that interval are never recorded as userHasScrolledUp. In practice the panel keeps auto-scrolling to the bottom even if the user scrolls up mid-stream, defeating the regression fix whenever messages arrive more often than 100ms.

Useful? React with 👍 / 👎.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
frontend/app/aipanel/aipanelmessages.tsx (3)

29-35: Consider documenting the 100ms timeout.

The 100ms delay is a reasonable heuristic to allow scroll events to settle before re-enabling user scroll detection. A brief inline comment explaining why this specific duration was chosen would help future maintainers.

             userHasScrolledUp.current = false;
+            // Delay resetting auto-scroll flag to allow scroll events to settle
             setTimeout(() => {
                 isAutoScrolling.current = false;
             }, 100);

59-60: Add passive option for better scroll performance.

The PR description mentions using a passive scroll event listener, but the passive option isn't set. Adding { passive: true } improves scroll performance by telling the browser that preventDefault() won't be called.

-        container.addEventListener("scroll", handleScroll);
-        return () => container.removeEventListener("scroll", handleScroll);
+        container.addEventListener("scroll", handleScroll, { passive: true });
+        return () => container.removeEventListener("scroll", handleScroll, { passive: true });

20-20: Remove unused messagesEndRef.

The messagesEndRef (line 20) and its corresponding div (line 117) appear to be unused. The scrollToBottom function now uses container.scrollTop directly instead of scrolling to the end element. Consider removing this dead code.

Remove the unused ref declaration at line 20:

-    const messagesEndRef = useRef<HTMLDivElement>(null);

And remove the unused div at line 117:

-            <div ref={messagesEndRef} />

Also applies to: 117-117

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fbb0c4d and cacd60a.

📒 Files selected for processing (1)
  • frontend/app/aipanel/aipanelmessages.tsx (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
frontend/app/aipanel/aipanelmessages.tsx (1)
frontend/app/aipanel/waveai-model.tsx (1)
  • scrollToBottom (288-290)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: merge-gatekeeper
🔇 Additional comments (4)
frontend/app/aipanel/aipanelmessages.tsx (4)

23-24: LGTM!

Using refs for scroll state tracking is the right choice here since these values shouldn't trigger re-renders and need to be accessed synchronously in event handlers.


67-72: LGTM!

The conditional auto-scroll correctly respects user intent by checking userHasScrolledUp before scrolling on message updates. This is the core fix for the PR objective.


74-78: Consider resetting scroll state when panel reopens.

When the panel is closed and reopened, the current implementation preserves userHasScrolledUp state. This means if a user scrolled up, closed the panel, and reopened it, auto-scroll would still be disabled. Consider whether a fresh panel open should reset the scroll state.

     useEffect(() => {
-        if (isPanelOpen && !userHasScrolledUp.current) {
+        if (isPanelOpen) {
+            userHasScrolledUp.current = false;
             scrollToBottom();
         }
     }, [isPanelOpen]);

80-91: LGTM!

The streaming completion handler correctly respects user scroll position. Using requestAnimationFrame ensures the DOM is settled before scrolling, and the userHasScrolledUp check preserves the user's reading position after streaming ends.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants