From ab1d3a6aa1364b14600fee042d2c17272c8668b5 Mon Sep 17 00:00:00 2001 From: Fusion Date: Sun, 24 May 2026 14:39:06 +0200 Subject: [PATCH 1/2] fix: use CSS Grid for mobile terminal layout Replace flexbox chains with CSS Grid to give content area definite height: - grid-template-rows: auto 1fr auto for header/content/keys - Use 100dvh for proper mobile viewport handling - Terminal fills content area with position: absolute - Remove mobile-terminal-shell wrapper (redundant) - Content area gets real height from grid, fixing FitAddon calculations --- apps/web/src/styles.css | 60 +++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 33 deletions(-) diff --git a/apps/web/src/styles.css b/apps/web/src/styles.css index cdf5f91..1ee421a 100644 --- a/apps/web/src/styles.css +++ b/apps/web/src/styles.css @@ -3062,15 +3062,15 @@ a.nav-item, Mobile Terminal Styles ============================================ */ -.mobile-terminal-shell { - height: 100vh; - overflow: hidden; -} - -.mobile-terminal-wrapper { - display: flex; - flex-direction: column; + .mobile-terminal-wrapper { + display: grid; + grid-template-rows: auto 1fr auto; + grid-template-areas: + "header" + "content" + "keys"; height: 100vh; + height: 100dvh; /* Dynamic viewport height for mobile */ background: #1e1e1e; position: relative; overflow: hidden; @@ -3078,13 +3078,13 @@ a.nav-item, /* Mobile Terminal Header */ .mobile-terminal-header { + grid-area: header; display: flex; align-items: center; justify-content: space-between; padding: var(--space-2) var(--space-3); background: #2d2d2d; border-bottom: 1px solid #3e3e3e; - flex-shrink: 0; transition: transform 0.3s ease, opacity 0.3s ease, height 0.3s ease, padding 0.3s ease, margin 0.3s ease; z-index: 100; overflow: hidden; @@ -3179,36 +3179,16 @@ a.nav-item, /* Mobile Terminal Content */ .mobile-terminal-content { - flex: 1; - min-height: 0; + grid-area: content; overflow: hidden; position: relative; - display: flex; - flex-direction: column; + background: #1e1e1e; } -/* Terminal wrapper - explicit height for xterm.js */ +/* Terminal wrapper - fills content area */ .terminal-wrapper.mobile { border: none; border-radius: 0; - flex: 1; - min-height: 0; - width: 100%; - overflow: hidden; - display: flex; - flex-direction: column; -} - -.terminal-wrapper.mobile .terminal-container { - flex: 1; - min-height: 0; - padding: 0; - overflow: hidden; - position: relative; -} - -/* Ensure xterm fills container */ -.terminal-wrapper.mobile .terminal-container .xterm { position: absolute; top: 0; left: 0; @@ -3216,10 +3196,25 @@ a.nav-item, bottom: 0; width: 100%; height: 100%; + overflow: hidden; +} + +.terminal-wrapper.mobile .terminal-container { + width: 100%; + height: 100%; + padding: 0; + overflow: hidden; +} + +/* xterm fills container */ +.terminal-wrapper.mobile .terminal-container .xterm { + width: 100%; + height: 100%; } /* Special Keys Strip */ .special-keys-strip { + grid-area: keys; display: flex; align-items: center; gap: 2px; @@ -3229,7 +3224,6 @@ a.nav-item, overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none; - flex-shrink: 0; transition: transform 0.3s ease, opacity 0.3s ease; z-index: 100; } From 865b9411da479c4e1953cc257381b47c06ea76b6 Mon Sep 17 00:00:00 2001 From: Fusion Date: Sun, 24 May 2026 14:43:27 +0200 Subject: [PATCH 2/2] fix: add 'resetting' status to terminal callback types TypeScript build failed because 'resetting' status was not included in the onTerminalReady callback type definition. Updated types in: - TerminalComponent props - MobileTerminalWrapper state and callback - MobileTerminalHeader props --- apps/web/src/components/mobile-terminal-header.tsx | 2 +- apps/web/src/components/mobile-terminal-wrapper.tsx | 4 ++-- apps/web/src/components/terminal.tsx | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/web/src/components/mobile-terminal-header.tsx b/apps/web/src/components/mobile-terminal-header.tsx index 920de97..a07c520 100644 --- a/apps/web/src/components/mobile-terminal-header.tsx +++ b/apps/web/src/components/mobile-terminal-header.tsx @@ -8,7 +8,7 @@ interface MobileTerminalHeaderProps { onClose?: () => void; onFontSizeChange?: (delta: number) => void; isVisible: boolean; - connectionStatus?: "connecting" | "connected" | "disconnected" | "error"; + connectionStatus?: "connecting" | "connected" | "disconnected" | "error" | "resetting"; } export const MobileTerminalHeader: React.FC = ({ diff --git a/apps/web/src/components/mobile-terminal-wrapper.tsx b/apps/web/src/components/mobile-terminal-wrapper.tsx index de7f1c4..9c33925 100644 --- a/apps/web/src/components/mobile-terminal-wrapper.tsx +++ b/apps/web/src/components/mobile-terminal-wrapper.tsx @@ -30,7 +30,7 @@ export const MobileTerminalWrapper: React.FC = ({ const [activeModifier, setActiveModifier] = useState(null); const [terminalRef, setTerminalRef] = useState<{ sendData: (data: string) => void; - connectionStatus: "connecting" | "connected" | "disconnected" | "error"; + connectionStatus: "connecting" | "connected" | "disconnected" | "error" | "resetting"; focusInput: () => void; changeFontSize: (delta: number) => void; } | null>(null); @@ -42,7 +42,7 @@ export const MobileTerminalWrapper: React.FC = ({ }, [headerAutoHide]); const handleTerminalReady = useCallback( - (sendData: (data: string) => void, connectionStatus: "connecting" | "connected" | "disconnected" | "error", focusInput: () => void, changeFontSize: (delta: number) => void) => { + (sendData: (data: string) => void, connectionStatus: "connecting" | "connected" | "disconnected" | "error" | "resetting", focusInput: () => void, changeFontSize: (delta: number) => void) => { setTerminalRef({ sendData, connectionStatus, focusInput, changeFontSize }); }, [] diff --git a/apps/web/src/components/terminal.tsx b/apps/web/src/components/terminal.tsx index fde4b05..e007a75 100644 --- a/apps/web/src/components/terminal.tsx +++ b/apps/web/src/components/terminal.tsx @@ -14,7 +14,7 @@ interface TerminalProps { onModifierChange?: (modifier: ModifierKey | null) => void; onTerminalReady?: ( sendData: (data: string) => void, - connectionStatus: "connecting" | "connected" | "disconnected" | "error", + connectionStatus: "connecting" | "connected" | "disconnected" | "error" | "resetting", focusInput: () => void, changeFontSize: (delta: number) => void ) => void;