Skip to content

Commit ad0cae6

Browse files
committed
feat: Do not lock scroll position while text is streaming
1 parent f678921 commit ad0cae6

2 files changed

Lines changed: 10 additions & 1 deletion

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,4 @@ vendor/opencode/
5151
.vercel
5252
.env*.local
5353
.claude/*
54+
.gstack/

apps/app/src/app/pages/session.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,7 @@ export default function SessionView(props: SessionViewProps) {
351351
let pendingScrollBehavior: ScrollBehavior = "auto";
352352
let lastAutoScrollAt = 0;
353353
let lastKnownScrollTop = 0;
354+
let userScrolledAwayAt = 0;
354355
let streamRenderBatchTimer: number | undefined;
355356
let streamRenderBatchQueuedAt = 0;
356357
let streamRenderBatchReschedules = 0;
@@ -2292,6 +2293,9 @@ export default function SessionView(props: SessionViewProps) {
22922293
runProgressSignature();
22932294
if (initialAnchorPending()) return;
22942295
if (!isViewingLatest()) return;
2296+
// Suppress auto-scroll for 800ms after user scrolled away to prevent fighting manual scroll
2297+
const timeSinceUserScroll = Date.now() - userScrolledAwayAt;
2298+
if (timeSinceUserScroll < 800) return;
22952299
scheduleScrollToLatest("auto");
22962300
});
22972301

@@ -4224,10 +4228,14 @@ export default function SessionView(props: SessionViewProps) {
42244228
const bottomGap =
42254229
container.scrollHeight -
42264230
(container.scrollTop + container.clientHeight);
4227-
if (bottomGap <= 96) {
4231+
// Use a small threshold (24px) to only pin when truly at bottom
4232+
// This prevents auto-scroll from fighting manual scroll during streaming
4233+
if (bottomGap <= 24) {
42284234
setIsViewingLatest(true);
42294235
} else if (container.scrollTop < lastKnownScrollTop - 1) {
4236+
// User scrolled up - respect their intent
42304237
setIsViewingLatest(false);
4238+
userScrolledAwayAt = Date.now();
42314239
}
42324240
lastKnownScrollTop = container.scrollTop;
42334241
refreshTopClippedMessage();

0 commit comments

Comments
 (0)