From e6da61f46036a6263080065dac14507eb8c4e434 Mon Sep 17 00:00:00 2001 From: Augustin Date: Fri, 24 Apr 2026 17:23:54 +0200 Subject: [PATCH] fix(terminal): use display:none instead of visibility for tab hiding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace visibility-based hiding with display property for reliable tab detection. Use offsetParent and offsetHeight checks instead of style properties to properly detect hidden terminals. 💘 Generated with Crush Assisted-by: MiniMax-M2.7 via Crush --- web/src/components/Shell.jsx | 25 ++++++++++--------------- web/src/styles/global.css | 1 - 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/web/src/components/Shell.jsx b/web/src/components/Shell.jsx index 64235ca..d03f1d9 100644 --- a/web/src/components/Shell.jsx +++ b/web/src/components/Shell.jsx @@ -400,7 +400,7 @@ export default function Shell({ api }) { const onResize = () => { const el = document.getElementById(`terminal-${tabId}`) - if (el && el.style.visibility !== 'hidden' && el.style.position !== 'absolute') { + if (el && el.style.display !== 'none') { fitAddon.fit() } } @@ -438,25 +438,23 @@ export default function Shell({ api }) { const tryInit = (attempt) => { if (cancelled || attempt > 20) return const shellCol = document.querySelector('.shell-terminal-col') - if (!shellCol) { + if (!shellCol || shellCol.offsetParent === null) { pending.push(setTimeout(() => tryInit(attempt + 1), 150)) return } const container = document.getElementById(`terminal-${tab.id}`) - if (!container) { + if (!container || container.offsetHeight === 0) { pending.push(setTimeout(() => tryInit(attempt + 1), 100)) return } if (!tabsRef.current[tab.id]) { initTerminal(tab.id, tab) } - if (activeTab === tab.id) { - requestAnimationFrame(() => { - if (cancelled) return - const entry = tabsRef.current[tab.id] - if (entry) entry.fitAddon.fit() - }) - } + requestAnimationFrame(() => { + if (cancelled) return + const entry = tabsRef.current[tab.id] + if (entry) entry.fitAddon.fit() + }) } tryInit(0) @@ -472,7 +470,7 @@ export default function Shell({ api }) { const entry = tabsRef.current[tab.id] if (entry) { const el = document.getElementById(`terminal-${tab.id}`) - if (el && el.style.visibility !== 'hidden') { + if (el && el.style.display !== 'none') { entry.fitAddon.fit() } } @@ -841,10 +839,7 @@ export default function Shell({ api }) { key={tab.id} id={`terminal-${tab.id}`} className="shell-xterm-instance" - style={activeTab === tab.id - ? { visibility: 'visible', pointerEvents: 'auto' } - : { visibility: 'hidden', pointerEvents: 'none' } - } + style={{ display: activeTab === tab.id ? 'block' : 'none' }} /> ))} diff --git a/web/src/styles/global.css b/web/src/styles/global.css index 9c69072..5436052 100644 --- a/web/src/styles/global.css +++ b/web/src/styles/global.css @@ -385,7 +385,6 @@ input::placeholder { color: var(--text-disabled); } .shell-xterm-wrapper { flex: 1; background: var(--bg); overflow: hidden; position: relative; } .shell-xterm-instance { position: absolute; inset: 0; padding: 4px; - display: block !important; } .shell-xterm-instance .xterm { height: 100%; padding: 4px; }