fix(terminal): improve tab visibility checks and positioning
All checks were successful
Beta Release / beta (push) Successful in 48s

- Add null check for container before accessing offsetHeight
- Validate activeTabRef during initialization and fit operations
- Check for display:none as visibility indicator
- Simplify useEffect dependency array
- Use absolute positioning for terminal wrapper/instance

💘 Generated with Crush

Assisted-by: MiniMax-M2.7 via Crush <crush@charm.land>
This commit is contained in:
Augustin
2026-04-24 17:59:48 +02:00
parent 3a09e0e0c2
commit 3cf701b002
2 changed files with 12 additions and 6 deletions

View File

@@ -443,7 +443,12 @@ export default function Shell({ api }) {
return return
} }
const container = document.getElementById(`terminal-${tab.id}`) const container = document.getElementById(`terminal-${tab.id}`)
if (!container || container.offsetHeight === 0) { if (!container) {
pending.push(setTimeout(() => tryInit(attempt + 1), 100))
return
}
if (activeTabRef.current !== tab.id) return
if (container.offsetHeight === 0 || container.style.display === 'none') {
pending.push(setTimeout(() => tryInit(attempt + 1), 100)) pending.push(setTimeout(() => tryInit(attempt + 1), 100))
return return
} }
@@ -452,6 +457,7 @@ export default function Shell({ api }) {
} }
requestAnimationFrame(() => { requestAnimationFrame(() => {
if (cancelled) return if (cancelled) return
if (activeTabRef.current !== tab.id) return
const entry = tabsRef.current[tab.id] const entry = tabsRef.current[tab.id]
if (entry) entry.fitAddon.fit() if (entry) entry.fitAddon.fit()
}) })
@@ -462,7 +468,7 @@ export default function Shell({ api }) {
cancelled = true cancelled = true
pending.forEach(clearTimeout) pending.forEach(clearTimeout)
} }
}, [activeTab, tabs, initTerminal]) }, [activeTab, initTerminal])
useEffect(() => { useEffect(() => {
const iv = setInterval(() => { const iv = setInterval(() => {

View File

@@ -382,12 +382,12 @@ input::placeholder { color: var(--text-disabled); }
} }
.shell-menu-divider { height: 1px; background: var(--border); margin: 4px 6px; } .shell-menu-divider { height: 1px; background: var(--border); margin: 4px 6px; }
.shell-xterm-wrapper { flex: 1; background: var(--bg); overflow: hidden; position: relative; } .shell-xterm-wrapper { flex: 1; height: 100%; background: var(--bg); overflow: hidden; position: relative; }
.shell-xterm-instance { .shell-xterm-instance {
height: 100%; position: absolute;
padding: 4px; inset: 0;
} }
.shell-xterm-instance .xterm { height: 100%; padding: 4px; } .shell-xterm-instance .xterm { height: 100%; }
.connection-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; flex-shrink: 0; } .connection-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; flex-shrink: 0; }
.connection-dot.on { background: var(--success); box-shadow: 0 0 6px var(--success); } .connection-dot.on { background: var(--success); box-shadow: 0 0 6px var(--success); }