Skip to content

Preserve chat scroll position while streaming new messages#51

Merged
juliusmarminge merged 1 commit intomainfrom
codething/25696837
Feb 15, 2026
Merged

Preserve chat scroll position while streaming new messages#51
juliusmarminge merged 1 commit intomainfrom
codething/25696837

Conversation

@juliusmarminge
Copy link
Copy Markdown
Member

@juliusmarminge juliusmarminge commented Feb 15, 2026

Summary

  • add isScrollContainerNearBottom utility to detect whether the messages container is close enough to the bottom to auto-scroll
  • track user scroll intent in ChatView with shouldAutoScrollRef and an onScroll handler
  • only auto-scroll on message/worklog updates when the user is near the bottom; keep forced scroll on thread switch
  • replace direct scrollTop/scrollIntoView calls with a shared scrollMessagesToBottom helper
  • add focused unit tests for threshold behavior, invalid inputs, and default fallback logic in chat-scroll.test.ts

Testing

  • apps/web/src/chat-scroll.test.ts: verifies near-bottom detection at bottom, within threshold, above threshold, negative threshold clamping, and NaN fallback
  • Manual check (expected): while a run is streaming, scrolling up in chat should no longer jump back to bottom until user returns near bottom
  • Not run: project lint and full test suite

Open with Devin

Summary by CodeRabbit

  • New Features

    • Improved automatic scrolling behavior for chat messages. Chat now intelligently scrolls to the latest message while respecting user scroll position when reading earlier messages.
    • Added smooth scrolling transitions for a better visual experience.
  • Tests

    • Added test coverage for scroll behavior validation.

- only auto-scroll when the user is already near the bottom
- centralize near-bottom detection in `chat-scroll.ts` with a 64px threshold
- add unit tests covering threshold and edge-case behavior

Co-authored-by: codex <codex@users.noreply.github.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 15, 2026

Walkthrough

This PR adds a scroll detection utility to determine when a chat scroll container is near the bottom, includes comprehensive tests for the utility, and integrates this logic into ChatView to implement conditional auto-scrolling that respects user scroll position.

Changes

Cohort / File(s) Summary
Scroll Detection Utility
apps/web/src/chat-scroll.ts, apps/web/src/chat-scroll.test.ts
Introduces AUTO_SCROLL_BOTTOM_THRESHOLD_PX constant (64px) and isScrollContainerNearBottom() function to detect scroll proximity. Tests validate threshold handling, negative value clamping, NaN fallback behavior, and distance calculations.
Chat Auto-Scroll Integration
apps/web/src/components/ChatView.tsx
Implements conditional auto-scrolling using scroll detection. Replaces unconditional scroll-on-update with smart scrolling via shouldAutoScrollRef state that tracks user scroll position and triggers smooth scrolling only when appropriate (near bottom or on thread change).

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant ChatView
    participant ScrollUtil as Scroll Utility
    participant DOM

    User->>DOM: Scrolls manually
    DOM->>ChatView: onScroll event fires
    ChatView->>ScrollUtil: isScrollContainerNearBottom()
    ScrollUtil->>ScrollUtil: Calculate distance from bottom
    ScrollUtil-->>ChatView: Returns boolean
    ChatView->>ChatView: Update shouldAutoScrollRef

    Note over ChatView: New message arrives
    ChatView->>ScrollUtil: isScrollContainerNearBottom()
    ScrollUtil-->>ChatView: Returns true (near bottom)
    ChatView->>DOM: smoothScrollToBottom()
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 3 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Preserve chat scroll position while streaming new messages' directly reflects the main change: implementing conditional auto-scroll behavior that respects user scroll intent rather than unconditionally jumping to the bottom when new messages arrive.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into main

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch codething/25696837

No actionable comments were generated in the recent review. 🎉

🧹 Recent nitpick comments
apps/web/src/chat-scroll.test.ts (1)

52-64: Consider adding a test for non-finite position metrics.

The implementation returns true when position metrics are non-finite (Lines 18-20 in chat-scroll.ts), but this behavior isn't tested. Adding a test would document this defensive behavior.

📝 Suggested test case
+  it("returns true when position metrics are non-finite", () => {
+    expect(
+      isScrollContainerNearBottom({
+        scrollTop: Number.NaN,
+        clientHeight: 400,
+        scrollHeight: 1_000,
+      }),
+    ).toBe(true);
+  });

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

@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Feb 15, 2026

Greptile Summary

This PR implements smart auto-scroll behavior for the chat interface that respects user scroll position. Previously, the chat would aggressively scroll to bottom on every message update, disrupting users trying to review earlier messages during streaming responses.

Key changes:

  • Added isScrollContainerNearBottom utility to detect if user is within 64px of bottom
  • Tracks user scroll intent in shouldAutoScrollRef updated via onScroll handler
  • Only auto-scrolls on message/worklog updates when user is near bottom
  • Always scrolls to bottom on thread switch (correct UX)
  • Consolidated scroll logic into scrollMessagesToBottom helper
  • Comprehensive unit tests cover threshold behavior and edge cases

Confidence Score: 5/5

  • This PR is safe to merge with no issues identified
  • Clean implementation with proper edge case handling, comprehensive tests, and clear UX improvement. No bugs or security concerns identified. Code follows React best practices using refs for non-render state and proper hook dependencies.
  • No files require special attention

Important Files Changed

Filename Overview
apps/web/src/chat-scroll.test.ts Added comprehensive unit tests for scroll position detection utility with edge cases
apps/web/src/chat-scroll.ts New utility to detect when scroll container is near bottom with threshold and fallback handling
apps/web/src/components/ChatView.tsx Implemented smart auto-scroll with user intent tracking via shouldAutoScrollRef and scroll handler

Flowchart

flowchart TD
    A[User Action] --> B{Thread Switch?}
    B -->|Yes| C[scrollMessagesToBottom - instant]
    B -->|No| D{New Message or WorkLog?}
    D -->|Yes| E{shouldAutoScrollRef.current?}
    E -->|true| F[scrollMessagesToBottom - smooth]
    E -->|false| G[No scroll - preserve position]
    D -->|No| G
    
    H[onMessagesScroll Event] --> I[isScrollContainerNearBottom]
    I --> J{Within 64px of bottom?}
    J -->|Yes| K[shouldAutoScrollRef = true]
    J -->|No| L[shouldAutoScrollRef = false]
    
    C --> M[Set shouldAutoScrollRef = true]
    F --> M
Loading

Last reviewed commit: 0476e50

@macroscopeapp
Copy link
Copy Markdown
Contributor

macroscopeapp bot commented Feb 15, 2026

Preserve chat scroll position in ChatView by auto-scrolling only when near bottom using a 64px threshold

Add AUTO_SCROLL_BOTTOM_THRESHOLD_PX (64) and isScrollContainerNearBottom in apps/web/src/chat-scroll.ts; update ChatView to compute shouldAutoScrollRef on scroll and call scrollMessagesToBottom only when within threshold; add tests in apps/web/src/chat-scroll.test.ts.

📍Where to Start

Start with isScrollContainerNearBottom in apps/web/src/chat-scroll.ts, then review how ChatView uses it in apps/web/src/components/ChatView.tsx.


Macroscope summarized 0476e50.

@juliusmarminge juliusmarminge merged commit 7fc53da into main Feb 15, 2026
4 checks passed
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.

1 participant