From 2ab2db91322b984ac02f01f1e1584571f0badc1a Mon Sep 17 00:00:00 2001 From: Jinwoo Hong <73622457+Jinwoo-H@users.noreply.github.com> Date: Wed, 22 Apr 2026 00:28:56 -0400 Subject: [PATCH] fix(terminal): add proportional scroll fallback for sidebar resize (#901) --- src/renderer/src/App.tsx | 22 +- .../components/terminal-pane/pane-helpers.ts | 12 +- .../terminal-pane/pty-connection.test.ts | 4 + .../terminal-pane/pty-connection.ts | 27 + .../use-terminal-pane-global-effects.ts | 83 +- src/renderer/src/constants/terminal.ts | 1 + src/renderer/src/hooks/useIpcEvents.test.ts | 2 +- src/renderer/src/hooks/useIpcEvents.ts | 3 + .../src/lib/pane-manager/pane-drag-scroll.ts | 146 +++- .../src/lib/pane-manager/pane-lifecycle.ts | 27 +- .../lib/pane-manager/pane-manager-types.ts | 11 + .../src/lib/pane-manager/pane-manager.ts | 85 +- .../src/lib/pane-manager/pane-scroll.ts | 122 ++- .../src/lib/pane-manager/pane-tree-ops.ts | 62 +- tests/e2e/fixtures/ink-tui-sim.mjs | 72 ++ tests/e2e/terminal-panes.spec.ts | 771 ++++++++++++++++++ 16 files changed, 1358 insertions(+), 92 deletions(-) create mode 100644 tests/e2e/fixtures/ink-tui-sim.mjs diff --git a/src/renderer/src/App.tsx b/src/renderer/src/App.tsx index 2c3a4683c95..294186c87b8 100644 --- a/src/renderer/src/App.tsx +++ b/src/renderer/src/App.tsx @@ -3,7 +3,11 @@ import { useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react' import { DEFAULT_STATUS_BAR_ITEMS, DEFAULT_WORKTREE_CARD_PROPERTIES } from '../../shared/constants' import { Minimize2, PanelLeft, PanelRight } from 'lucide-react' -import { FOCUS_TERMINAL_PANE_EVENT, TOGGLE_TERMINAL_PANE_EXPAND_EVENT } from '@/constants/terminal' +import { + FOCUS_TERMINAL_PANE_EVENT, + LAYOUT_WILL_CHANGE_EVENT, + TOGGLE_TERMINAL_PANE_EXPAND_EVENT +} from '@/constants/terminal' import { syncZoomCSSVar } from '@/lib/ui-zoom' import { toast } from 'sonner' import { Toaster } from '@/components/ui/sonner' @@ -499,6 +503,7 @@ function App(): React.JSX.Element { if (!e.altKey && !e.shiftKey && e.key.toLowerCase() === 'b') { dispatchClearModifierHints() e.preventDefault() + window.dispatchEvent(new Event(LAYOUT_WILL_CHANGE_EVENT)) actions.toggleSidebar() return } @@ -519,6 +524,7 @@ function App(): React.JSX.Element { if (!e.altKey && !e.shiftKey && e.key.toLowerCase() === 'l') { dispatchClearModifierHints() e.preventDefault() + window.dispatchEvent(new Event(LAYOUT_WILL_CHANGE_EVENT)) actions.toggleRightSidebar() return } @@ -527,6 +533,7 @@ function App(): React.JSX.Element { if (e.shiftKey && !e.altKey && e.key.toLowerCase() === 'e') { dispatchClearModifierHints() e.preventDefault() + window.dispatchEvent(new Event(LAYOUT_WILL_CHANGE_EVENT)) actions.setRightSidebarTab('explorer') actions.setRightSidebarOpen(true) return @@ -536,6 +543,7 @@ function App(): React.JSX.Element { if (e.shiftKey && !e.altKey && e.key.toLowerCase() === 'f') { dispatchClearModifierHints() e.preventDefault() + window.dispatchEvent(new Event(LAYOUT_WILL_CHANGE_EVENT)) actions.setRightSidebarTab('search') actions.setRightSidebarOpen(true) return @@ -552,6 +560,7 @@ function App(): React.JSX.Element { } dispatchClearModifierHints() e.preventDefault() + window.dispatchEvent(new Event(LAYOUT_WILL_CHANGE_EVENT)) actions.setRightSidebarTab('source-control') actions.setRightSidebarOpen(true) } @@ -597,7 +606,10 @@ function App(): React.JSX.Element {