Skip to content

fix(thread): stop ChatThread snapping to top on prompt submit#3083

Merged
frankh merged 4 commits into
mainfrom
posthog-code/fix-chatthread-snap-to-top
Jul 2, 2026
Merged

fix(thread): stop ChatThread snapping to top on prompt submit#3083
frankh merged 4 commits into
mainfrom
posthog-code/fix-chatthread-snap-to-top

Conversation

@frankh

@frankh frankh commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Problem

In the new ChatThread view (behind useNewChatThread):

  1. Submitting a prompt in a conversation with history snapped the scroll position back to the top of the conversation on every prompt.
  2. Stick-to-bottom was unreliable: submits and streaming replies often didn't scroll the view, and fast streams (large blocks) dropped out of follow mid-reply.

Root causes

The snap. quill's message scroller reacts to childList mutations on the scroller content by comparing direct-child counts. When a prompt is sent, the optimistic user bubble (optimistic-… id) is swapped for the echoed real prompt (turn-…-user id) in a single React commit — a mutation where the child count doesn't change. In that case the engine falls into a re-anchor branch that scans all rows from the top for the first data-scroll-anchor element it hasn't scrolled to before. Historical user messages never qualify as handled, so it scrolls to the first user message in the conversation. A second trigger of the same branch: a lone tool marker collapsing into a tool_group row (1 row → 1 row, key change) mid-response.

Unreliable following. The engine only auto-follows in following-bottom mode, which it re-enters solely within scrollEdgeThreshold (default 8px) of the exact bottom — with the thread's bottom padding the view is rarely that close, and any stray trackpad wheel exits follow mode. Additionally, each engine autoscroll is guarded by a 180ms grace window; a large streamed block (heavy markdown render) can jank past it, making the engine observe "content below the fold while not autoscrolling" and demote itself to free-scrolling mid-reply.

Fix

All in ChatThread.tsx:

  • Key user-message rows by occurrence index (user-turn-N) instead of item.id, so the optimistic→real swap reuses the same DOM element and the buggy re-anchor branch never fires.
  • Reuse the first tool's item id as the tool_group id, so a lone marker growing into a group keeps its key/element.
  • ThreadAutoFollow: pin the view to the bottom from prompt submit until the user scrolls away — scroll to end on submit (which also re-engages the engine's following-bottom), and while armed re-issue scrollToEnd whenever content slips below the fold, recapturing follow after stream bursts. User scroll intent (wheel/touch/pointer/keys) disarms.
  • Widen scrollEdgeThreshold to 100px so near-bottom counts as at-bottom for the engine's own follow-mode recapture.

Follow-up: the underlying count-neutral re-anchor bug should also be fixed upstream in @posthog/quill's message scroller.


Created with PostHog Code

Stable row keys keep the optimistic user bubble's DOM element across the
echoed-prompt swap and a lone tool marker's element across tool-group
collapse, so quill's message scroller never sees a count-neutral childList
mutation (its re-anchor fallback scrolls to the first never-handled anchor,
i.e. the first user message in the conversation). New prompts now anchor to
the viewport top explicitly via scrollToMessage, since the engine's implicit
anchor path can't fire while the footer is a scroller-content child.

Generated-By: PostHog Code
Task-Id: c30ae5a8-6f18-4a44-882e-a1b29ea84154
@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown

React Doctor found no issues in the changed files. 🎉

Reviewed by React Doctor for commit 8867aec.

@greptile-apps

greptile-apps Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Reviews (1): Last reviewed commit: "fix(thread): stop ChatThread snapping to..." | Re-trigger Greptile

frankh added 2 commits July 2, 2026 11:18
Generated-By: PostHog Code
Task-Id: c30ae5a8-6f18-4a44-882e-a1b29ea84154
The scroller only auto-follows in following-bottom mode, which it re-enters
solely within 8px of the exact bottom. With the thread's bottom padding the
view is rarely that close, and any stray trackpad wheel drops out of follow
mode permanently. Scroll to end on every user submit (which also re-engages
follow mode for the streaming reply) and widen the edge threshold to 100px
so near-bottom counts as at-bottom for recapture.

Generated-By: PostHog Code
Task-Id: c30ae5a8-6f18-4a44-882e-a1b29ea84154
@frankh frankh added Create Release This will trigger a new release Stamphog This will request an autostamp by stamphog on small changes labels Jul 2, 2026
github-actions[bot]
github-actions Bot previously approved these changes Jul 2, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No showstoppers — this is a focused, self-contained UI scroll-behavior fix with no data model, API contract, or business logic changes. The tool_group id simplification is safe (no key collision), the new ScrollToEndOnSubmit component uses correct React patterns, and the wider scroll threshold is a reasonable UX improvement.

@frankh frankh enabled auto-merge (squash) July 2, 2026 10:35
@frankh frankh disabled auto-merge July 2, 2026 10:36
…n it

The engine guards each autoscroll with a 180ms grace window; a big streamed
block can jank past it, so the engine sees content below the fold while not
autoscrolling and demotes itself to free-scrolling mid-reply. Arm a pin on
submit that re-issues scrollToEnd whenever content slips below the fold,
disarmed by user scroll intent.

Generated-By: PostHog Code
Task-Id: c30ae5a8-6f18-4a44-882e-a1b29ea84154
@github-actions github-actions Bot dismissed their stale review July 2, 2026 10:40

New commits pushed (delta classified non_trivial_delta) — stamphog approval dismissed; re-review running automatically.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No showstoppers — this is a self-contained UI scroll-behavior fix with no data model, API contract, business logic, or security implications.

@frankh frankh enabled auto-merge (squash) July 2, 2026 10:43
@frankh frankh merged commit 7b32529 into main Jul 2, 2026
23 checks passed
@frankh frankh deleted the posthog-code/fix-chatthread-snap-to-top branch July 2, 2026 10:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Create Release This will trigger a new release Stamphog This will request an autostamp by stamphog on small changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant