From 05a4b23d88ae7141f22c461440de9e51b7c1e687 Mon Sep 17 00:00:00 2001 From: Jannis Braun <151788261+TheZwiss@users.noreply.github.com> Date: Mon, 23 Mar 2026 15:04:44 +0100 Subject: [PATCH] fix: prevent scroll snap-back during mobile momentum scrolling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ResizeObserver and media load callbacks were using isNearBottomRef (5000px threshold) to decide whether to auto-scroll to bottom. On mobile, inertial flick scrolling hadn't moved far enough to clear that threshold before the observer fired, snapping the user back. Now these callbacks check actual scroll distance at fire time with a tight 150px threshold — only auto-scrolls if truly at the bottom. --- .../web/src/components/chat/MessageList.tsx | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/packages/web/src/components/chat/MessageList.tsx b/packages/web/src/components/chat/MessageList.tsx index dbe0e590..9b05f750 100644 --- a/packages/web/src/components/chat/MessageList.tsx +++ b/packages/web/src/components/chat/MessageList.tsx @@ -159,8 +159,14 @@ export function MessageList({ channelId, jumpToMessageId, onJumpComplete }: Mess if (!content || !container) return; const observer = new ResizeObserver(() => { - if (isNearBottomRef.current && containerRef.current) { - containerRef.current.scrollTop = containerRef.current.scrollHeight; + const c = containerRef.current; + if (!c) return; + // Use a tight threshold (150px) checked at fire time instead of the + // generous 5000px isNearBottomRef — prevents snapping the user back + // to bottom during momentum/inertial scrolling on mobile. + const dist = c.scrollHeight - c.scrollTop - c.clientHeight; + if (dist < 150) { + c.scrollTop = c.scrollHeight; } }); observer.observe(content); @@ -175,8 +181,11 @@ export function MessageList({ channelId, jumpToMessageId, onJumpComplete }: Mess if (!content) return; const handleMediaLoad = () => { - if (isNearBottomRef.current && containerRef.current) { - containerRef.current.scrollTop = containerRef.current.scrollHeight; + const c = containerRef.current; + if (!c) return; + const dist = c.scrollHeight - c.scrollTop - c.clientHeight; + if (dist < 150) { + c.scrollTop = c.scrollHeight; } };