From 6e496e102d4c30780cfaf4afaf4fac00be6f2cd1 Mon Sep 17 00:00:00 2001 From: Fusion Date: Sun, 24 May 2026 14:14:45 +0200 Subject: [PATCH] fix: terminal sizing and newline rendering issues - Add ResizeObserver to terminal container for responsive sizing (catches keyboard open/close, header auto-hide, layout changes) - Remove padding from mobile terminal container to maximize space - Fix CSS: ensure xterm viewport fills container height properly - Fix session-card.tsx TypeScript error (removed non-existent port field) - Remove explicit xterm-viewport/xterm-screen width overrides that interfered with xterm.js canvas sizing --- apps/web/src/components/session-card.tsx | 4 +--- apps/web/src/components/terminal.tsx | 22 ++++++++++++++++++ apps/web/src/styles.css | 29 +++++++++++++----------- 3 files changed, 39 insertions(+), 16 deletions(-) diff --git a/apps/web/src/components/session-card.tsx b/apps/web/src/components/session-card.tsx index a1e6c88..a84686e 100644 --- a/apps/web/src/components/session-card.tsx +++ b/apps/web/src/components/session-card.tsx @@ -110,9 +110,7 @@ export function SessionCard({

)} - {session.port && session.status === "running" && ( -

Port: {session.port}

- )} + {session.created_at && (

Created: {new Date(session.created_at).toLocaleDateString()} diff --git a/apps/web/src/components/terminal.tsx b/apps/web/src/components/terminal.tsx index a273930..5040fd4 100644 --- a/apps/web/src/components/terminal.tsx +++ b/apps/web/src/components/terminal.tsx @@ -242,6 +242,25 @@ export const TerminalComponent: React.FC = ({ window.addEventListener("resize", handleResize); + // Watch container size changes (keyboard, header auto-hide, etc.) + let resizeObserver: ResizeObserver | null = null; + if (terminalRef.current && typeof ResizeObserver !== "undefined") { + resizeObserver = new ResizeObserver(() => { + fitAddon.fit(); + const { cols, rows } = term; + if (ws.readyState === WebSocket.OPEN) { + ws.send( + JSON.stringify({ + type: "resize", + cols, + rows, + }) + ); + } + }); + resizeObserver.observe(terminalRef.current); + } + // Notify parent about terminal readiness if (onTerminalReadyRef.current) { const sendData = (data: string) => { @@ -270,6 +289,9 @@ export const TerminalComponent: React.FC = ({ return () => { clearTimeout(resizeTimeout); window.removeEventListener("resize", handleResize); + if (resizeObserver) { + 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 95b9933..3ab60b6 100644 --- a/apps/web/src/styles.css +++ b/apps/web/src/styles.css @@ -2594,31 +2594,34 @@ a.nav-item, padding: var(--space-2); display: flex; flex-direction: column; + overflow: hidden; } .terminal-container .xterm { flex: 1; min-height: 0; width: 100%; -} - -.terminal-container .xterm-viewport { - width: 100% !important; - height: 100% !important; -} - -.terminal-container .xterm-screen { - width: 100% !important; -} - -.terminal-container .xterm-viewport { - background: #1e1e1e !important; + height: 100%; } .terminal-container canvas { display: block; } +/* Mobile terminal container - no padding to maximize space */ +.terminal-wrapper.mobile .terminal-container { + padding: 0; +} + +/* Ensure xterm viewport fills container properly */ +.terminal-wrapper.mobile .xterm { + height: 100% !important; +} + +.terminal-wrapper.mobile .xterm-viewport { + height: 100% !important; +} + /* Responsive terminal */ @media (max-width: 767px) { .terminal-page {