From fe98f966d63ed913b91343521f317fe913632968 Mon Sep 17 00:00:00 2001 From: Alex Blank Date: Fri, 29 May 2026 11:11:03 +0200 Subject: [PATCH] fix: allow Escape in terminal, exit fullscreen on click outside - Remove global Escape key listener that intercepted Escape before xterm.js could receive it, breaking vim/tmux/etc. - Add click-outside-to-exit for fullscreen: clicking on the padding area around .terminal-page-content or .terminal-fullscreen-header exits fullscreen. Clicks inside content or header are ignored. - Add 8px padding/gap to .terminal-page.fullscreen to create a clickable border area around the terminal. - Keep Exit button and Alt+Shift+F as explicit exit methods. Quality gates: tsc --noEmit (clean), pytest (208 passed, 6 pre-existing) --- apps/web/src/pages/terminal.tsx | 29 ++++++++++++++++++----------- apps/web/src/styles.css | 4 ++-- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/apps/web/src/pages/terminal.tsx b/apps/web/src/pages/terminal.tsx index 4efa750..1d4f03a 100644 --- a/apps/web/src/pages/terminal.tsx +++ b/apps/web/src/pages/terminal.tsx @@ -162,17 +162,21 @@ export const TerminalPage: React.FC = () => { setActiveSessionId, ]); - // Exit fullscreen on Escape - useEffect(() => { - if (!isFullscreen) return; - const handleEscape = (e: KeyboardEvent) => { - if (e.key === "Escape") { - setIsFullscreen(false); + // Click outside terminal content/header to exit fullscreen + const handleFullscreenClick = useCallback( + (e: React.MouseEvent) => { + if (!isFullscreen) return; + const target = e.target as Node; + const current = e.currentTarget as HTMLElement; + const content = current.querySelector(".terminal-page-content"); + const header = current.querySelector(".terminal-fullscreen-header"); + if (content?.contains(target) || header?.contains(target)) { + return; } - }; - window.addEventListener("keydown", handleEscape); - return () => window.removeEventListener("keydown", handleEscape); - }, [isFullscreen]); + setIsFullscreen(false); + }, + [isFullscreen], + ); const handleSelect = useCallback( (sessionId: string) => { @@ -302,7 +306,10 @@ export const TerminalPage: React.FC = () => { } return ( -
+
{!isFullscreen && (