Skip to content

fix(console-ui): chat transcript snapping during live status updates - #1083

Merged
ndizazzo merged 2 commits into
Mesh-LLM:mainfrom
bradleydwyer:agent/preserve-chat-scroll-position
Jul 26, 2026
Merged

fix(console-ui): chat transcript snapping during live status updates#1083
ndizazzo merged 2 commits into
Mesh-LLM:mainfrom
bradleydwyer:agent/preserve-chat-scroll-position

Conversation

@bradleydwyer

@bradleydwyer bradleydwyer commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Fixes #1077.

Original problem

In live mode, frequent status updates rerendered ChatLayout, whose layout effect unconditionally returned the transcript to the latest message. Readers scrolling through a long response were repeatedly snapped back to the bottom.

Diagnostics

The live status stream produced 49 payloads in 12 seconds. Each payload updated the status query, rerendered the chat layout, and ran the unconditional scroll effect. Safari applied the user's scroll normally before the next React render overwrote the position.

Fix

  • Track whether the transcript is within 64px of the bottom and only follow new content while that remains true.
  • Resume following when the reader returns near the bottom.
  • Return to the latest message on conversation switches and explicit Send, Queue, or Retry actions.
  • Re-check reader intent inside the deferred animation-frame scroll.
  • Add regression coverage for unrelated rerenders, threshold behavior, conversation changes, send/queue/retry flows, and the animation-frame race.

This is a UI-only behavior change with no protocol, storage, or migration impact.

Summary by CodeRabbit

  • New Features

    • Chat transcripts now preserve your manual scroll position when you read older messages.
    • Automatic scrolling resumes when you’re near the bottom of the conversation.
    • Sending a message, retrying a response, or switching conversations returns the view to the latest message.
  • Bug Fixes

    • Prevented delayed scrolling from overriding upward scrolling.
    • Improved transcript positioning during live updates, retries, and queued messages.

@github-actions

Copy link
Copy Markdown
Contributor

This pull request is currently a draft. Reviews will not take place until the PR is marked as ready for review.

@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

ChatLayout now preserves manual transcript positions unless the reader is near the bottom. ChatPageContent resets bottom-sticking when conversations change or new and retried turns begin, with expanded tests covering these scroll flows.

Changes

Chat transcript scrolling

Layer / File(s) Summary
Conditional transcript scrolling
crates/mesh-llm-ui/src/features/chat/layouts/ChatLayout.tsx
Tracks distance from the transcript bottom, conditionally performs automatic scrolling, resets on stickToBottomKey changes, and wires scroll events from the message list.
Latest-turn reset wiring
crates/mesh-llm-ui/src/features/chat/pages/ChatPage.tsx
Adds latestTurnToken, increments it for sends and retries, and passes it with the conversation ID as stickToBottomKey.
Scroll behavior test coverage
crates/mesh-llm-ui/src/features/chat/pages/ChatPage.test.tsx
Adds deterministic scroll geometry helpers and tests for manual positions, threshold behavior, queued frames, conversation changes, retries, sends, and queued prompts.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ChatPageContent
  participant ChatLayout
  participant MessageList
  ChatPageContent->>ChatLayout: pass stickToBottomKey
  MessageList->>ChatLayout: report scroll position
  ChatLayout->>MessageList: scroll to latest when enabled
Loading

Suggested reviewers: ndizazzo, i386

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The implementation matches #1077 by tracking bottom proximity, preserving user scroll position, and resetting on conversation changes.
Out of Scope Changes check ✅ Passed The changes stay within the chat scroll-behavior fix and supporting tests, with no obvious unrelated scope added.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main UI fix: preventing chat transcript snapping during live status updates.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@bradleydwyer
bradleydwyer marked this pull request as ready for review July 26, 2026 05:03
@github-actions
github-actions Bot requested a review from i386 July 26, 2026 05:03
@ndizazzo ndizazzo changed the title Fix chat transcript snapping during live status updates fix(console-ui): chat transcript snapping during live status updates Jul 26, 2026
@ndizazzo
ndizazzo merged commit 2393c61 into Mesh-LLM:main Jul 26, 2026
31 of 44 checks passed
@ndizazzo

Copy link
Copy Markdown
Collaborator

Thanks for the fix @bradleydwyer!

michaelneale added a commit that referenced this pull request Jul 27, 2026
* origin/main:
  Fix Metal small-batch matmul parity for GLM verification (#1078)
  Handle K-only transposed KV page import and export (#1084)
  Refresh llama.cpp upstream patch queue (#1085)
  chore: improve embedded native-runtime compatibility guidance (#1043)
  fix(console-ui): chat transcript snapping during live status updates (#1083)
  ci: bump Linux CUDA slim container to gha-convention base runner image
  fix: record activation cache prefix identities (#1041)
  fix: read-only model download caches (#1042)
  ci: disable sccache for Windows ROCm native runtime build (#1087)
  ci: fix v0.74 release GPU builds (sccache disk-only + force_hosted_runners) (#1086)
  Make release sccache failures non-fatal (#1079)
  Keep client-only nodes out of model election (#1074)

# Conflicts:
#	crates/mesh-llm-host-runtime/src/runtime/auto_join.rs
#	crates/mesh-llm-host-runtime/src/runtime/tests/auto_join.rs
#	third_party/llama.cpp/patches/0004-Add-lanes-external-media-and-chat-grammar-support.patch
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.

Chat transcript snaps back to bottom during live status updates

2 participants