From b5dbb3cff92a5befcc354d67b064b1571209ba12 Mon Sep 17 00:00:00 2001 From: luckeyfaraday Date: Thu, 9 Jul 2026 18:26:57 +0200 Subject: [PATCH] Reflow terminal panes when a sibling is spawned MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A pane's native `resize: vertical` handle writes an inline height directly onto the DOM node. React never manages that property, so it is never cleared, which left a previously resized pane pinned at its old height when a new pane was spawned below it — the pane above refused to shrink and the new pane rendered into a stale layout. Clear the inline height on every visible pane whenever the pane set changes, so the grid re-tiles all of them (which also fires each pane's ResizeObserver and refits its xterm). Switch the non-focused embedded stage to an equal share-space grid (minmax(0, 1fr) + stretch, min-height 0) so panes actually shrink to make room instead of scrolling. Co-Authored-By: Claude Opus 4.8 --- client/src/rooms/CommandRoom.tsx | 12 ++++++++++++ client/src/styles.css | 6 +++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/client/src/rooms/CommandRoom.tsx b/client/src/rooms/CommandRoom.tsx index 31f745a..81f3332 100644 --- a/client/src/rooms/CommandRoom.tsx +++ b/client/src/rooms/CommandRoom.tsx @@ -89,6 +89,7 @@ export function CommandRoom({ const dragStartRef = useRef<{ id: string; x: number; y: number } | null>(null); const dragTargetRef = useRef(null); const newMenuRef = useRef(null); + const stageRef = useRef(null); const workspaceOrderKey = normalizeWorkspaceKey(workspace || "none"); const sessionIds = sessions.map((session) => session.id); const sessionSignature = sessionIds.join("|"); @@ -133,6 +134,16 @@ export function CommandRoom({ const displayedTerminalSessions = activeMaximizedPaneId ? visibleSessions.filter((session) => session.id === activeMaximizedPaneId) : visibleSessions; + + // The native `resize: vertical` handle on a pane writes an inline height straight onto + // the DOM node, which React never manages and so never clears. That pinned height keeps + // a previously resized pane from shrinking when a sibling is spawned below it, so clear + // it whenever the visible pane set changes and let the grid re-tile every pane. + useEffect(() => { + stageRef.current?.querySelectorAll(".slotPane").forEach((pane) => { + pane.style.height = ""; + }); + }, [visibleSessionKey]); const visibleAgentSessions = agentSessions.filter((session) => !deletedSessionKeys.has(agentSessionKey(session))); const providerTabs = useMemo(() => { const counts = new Map([["all", visibleAgentSessions.length]]); @@ -356,6 +367,7 @@ export function CommandRoom({ {activeTab === "terminals" ? (