From 74c65068c8c14a4ec731acdf3c9506a60134b288 Mon Sep 17 00:00:00 2001 From: Fusion Date: Sun, 24 May 2026 13:42:39 +0200 Subject: [PATCH 1/2] fix: add ResizeObserver and delayed fit for terminal sizing - Add ResizeObserver to watch terminal container and trigger fit() on size changes - Add delayed second fit() call 500ms after initialization - Remove initial setTimeout resize in favor of ResizeObserver - Ensure resizeObserver is cleaned up on unmount --- apps/web/src/components/terminal.tsx | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/apps/web/src/components/terminal.tsx b/apps/web/src/components/terminal.tsx index 63a5de5..2cb4fcd 100644 --- a/apps/web/src/components/terminal.tsx +++ b/apps/web/src/components/terminal.tsx @@ -167,10 +167,24 @@ export const TerminalComponent: React.FC = ({ // Connect WebSocket const ws = connectWebSocket(); - // Fit after layout settles - use rAF to ensure DOM is ready + // Fit after layout settles - use rAF + timeout to ensure DOM is ready requestAnimationFrame(() => { requestAnimationFrame(() => { fitAddon.fit(); + // Force a second fit after layout fully settles + setTimeout(() => { + fitAddon.fit(); + const { cols, rows } = term; + if (ws.readyState === WebSocket.OPEN) { + ws.send( + JSON.stringify({ + type: "resize", + cols, + rows, + }) + ); + } + }, 500); }); }); @@ -213,8 +227,13 @@ export const TerminalComponent: React.FC = ({ window.addEventListener("resize", handleResize); - // Initial resize - setTimeout(handleResize, 100); + // Use ResizeObserver to detect container size changes + const resizeObserver = new ResizeObserver(() => { + handleResize(); + }); + if (terminalRef.current) { + resizeObserver.observe(terminalRef.current); + } // Notify parent about terminal readiness if (onTerminalReadyRef.current) { @@ -244,6 +263,7 @@ export const TerminalComponent: React.FC = ({ return () => { clearTimeout(resizeTimeout); window.removeEventListener("resize", handleResize); + resizeObserver.disconnect(); document.removeEventListener("visibilitychange", handleVisibilityChange); ws.close(); term.dispose(); From e265c869973673f088fde4db8bb075fc78ac0818 Mon Sep 17 00:00:00 2001 From: Fusion Date: Sun, 24 May 2026 13:47:40 +0200 Subject: [PATCH 2/2] fix: use flex layout for terminal container to ensure proper sizing - Remove ResizeObserver that was causing infinite resize loop - Add display: flex to terminal-container for proper child sizing - Use flex: 1 on .xterm element instead of height: 100% - Remove explicit height/width from xterm-viewport and xterm-screen - Let flexbox handle the layout naturally --- apps/web/src/components/terminal.tsx | 9 --------- apps/web/src/styles.css | 13 ++++--------- 2 files changed, 4 insertions(+), 18 deletions(-) diff --git a/apps/web/src/components/terminal.tsx b/apps/web/src/components/terminal.tsx index 2cb4fcd..a6eddf1 100644 --- a/apps/web/src/components/terminal.tsx +++ b/apps/web/src/components/terminal.tsx @@ -227,14 +227,6 @@ export const TerminalComponent: React.FC = ({ window.addEventListener("resize", handleResize); - // Use ResizeObserver to detect container size changes - const resizeObserver = new ResizeObserver(() => { - handleResize(); - }); - if (terminalRef.current) { - resizeObserver.observe(terminalRef.current); - } - // Notify parent about terminal readiness if (onTerminalReadyRef.current) { const sendData = (data: string) => { @@ -263,7 +255,6 @@ export const TerminalComponent: React.FC = ({ return () => { clearTimeout(resizeTimeout); window.removeEventListener("resize", handleResize); - resizeObserver.disconnect(); document.removeEventListener("visibilitychange", handleVisibilityChange); ws.close(); term.dispose(); diff --git a/apps/web/src/styles.css b/apps/web/src/styles.css index 5caf2ad..957804f 100644 --- a/apps/web/src/styles.css +++ b/apps/web/src/styles.css @@ -2592,24 +2592,19 @@ a.nav-item, flex: 1; min-height: 0; padding: var(--space-2); + display: flex; + flex-direction: column; } .terminal-container .xterm { - height: 100%; - width: 100%; + flex: 1; + min-height: 0; } .terminal-container .xterm-viewport { - height: 100% !important; - width: 100% !important; background: #1e1e1e !important; } -.terminal-container .xterm-screen { - height: 100% !important; - width: 100% !important; -} - .terminal-container canvas { display: block; }