From d34e8e2c6d115f28597890b2abed28f6a68a724b Mon Sep 17 00:00:00 2001 From: Josh Knapp Date: Sat, 14 Mar 2026 21:35:58 -0700 Subject: [PATCH] Fix jump-to-bottom button broken during active terminal output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The shouldFollow flag was captured before term.write() but the callback ran asynchronously — if the user scrolled up in between, the stale flag forced the viewport back to bottom, preventing the button from appearing. Check isAtBottomRef at callback time instead so user scroll-up is respected. Co-Authored-By: Claude Opus 4.6 (1M context) --- app/src/components/terminal/TerminalView.tsx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/app/src/components/terminal/TerminalView.tsx b/app/src/components/terminal/TerminalView.tsx index 2bb5be5..c2dd0d7 100644 --- a/app/src/components/terminal/TerminalView.tsx +++ b/app/src/components/terminal/TerminalView.tsx @@ -197,13 +197,12 @@ export default function TerminalView({ sessionId, active }: Props) { const outputPromise = onOutput(sessionId, (data) => { if (aborted) return; - const shouldFollow = isAtBottomRef.current; term.write(data, () => { - // Keep viewport pinned to bottom when user hasn't scrolled up - if (shouldFollow) { + // Keep viewport pinned to bottom when user hasn't scrolled up. + // Check ref at callback time (not capture time) so that a user + // scroll-up between the write() call and callback is respected. + if (isAtBottomRef.current) { term.scrollToBottom(); - isAtBottomRef.current = true; - setIsAtBottom(true); } }); detector.feed(data);