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();