From add73ad6879c56edf36cb351461ec0fe6ed816d5 Mon Sep 17 00:00:00 2001 From: Bohdan Triapitsyn Date: Thu, 7 May 2026 19:03:55 +0300 Subject: [PATCH] fix: keep terminal shortcuts working without blanking chat Terminal toggle shortcuts work while the terminal is focused Hiding an expanded terminal no longer leaves a blank page --- .../components/layout/BottomTerminalDock.tsx | 5 ++- packages/ui/src/hooks/useKeyboardShortcuts.ts | 40 +++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/packages/ui/src/components/layout/BottomTerminalDock.tsx b/packages/ui/src/components/layout/BottomTerminalDock.tsx index 5ec60a66..0f854184 100644 --- a/packages/ui/src/components/layout/BottomTerminalDock.tsx +++ b/packages/ui/src/components/layout/BottomTerminalDock.tsx @@ -104,6 +104,7 @@ export const BottomTerminalDock: React.FC = ({ isOpen, const appliedHeight = isOpen ? (isFullscreen ? Math.max(0, fullscreenHeight ?? standardHeight) : standardHeight) : 0; + const shouldApplyFullscreenLayout = isOpen && isFullscreen; const handlePointerDown = (event: React.PointerEvent) => { if (!isOpen || isFullscreen) return; @@ -118,11 +119,11 @@ export const BottomTerminalDock: React.FC = ({ isOpen, ref={dockRef} className={cn( 'flex overflow-hidden border-t border-border bg-sidebar', - isFullscreen ? 'absolute inset-x-0 bottom-0 z-40' : 'relative', + shouldApplyFullscreenLayout ? 'absolute inset-x-0 bottom-0 z-40' : 'relative', isResizing ? 'transition-none' : 'transition-[height] duration-300 ease-in-out', !isOpen && 'border-t-0' )} - style={isFullscreen ? { + style={shouldApplyFullscreenLayout ? { top: 'var(--oc-header-height, 48px)', } : { height: `${appliedHeight}px`, diff --git a/packages/ui/src/hooks/useKeyboardShortcuts.ts b/packages/ui/src/hooks/useKeyboardShortcuts.ts index 187a5d29..10ea2fc9 100644 --- a/packages/ui/src/hooks/useKeyboardShortcuts.ts +++ b/packages/ui/src/hooks/useKeyboardShortcuts.ts @@ -54,6 +54,44 @@ export const useKeyboardShortcuts = () => { React.useEffect(() => { const combo = (actionId: string) => getEffectiveShortcutCombo(actionId, shortcutOverrides); + const isTerminalEventTarget = (target: EventTarget | null) => { + if (!(target instanceof Element)) { + return false; + } + + return Boolean( + target.closest('.terminal-viewport-container') || + target.getAttribute('data-terminal-hidden-input') === 'true' + ); + }; + + const handleTerminalShortcutCapture = (e: KeyboardEvent) => { + if (!isTerminalEventTarget(e.target)) { + return; + } + + if (eventMatchesShortcut(e, combo('toggle_terminal'))) { + const { isMobile } = useUIStore.getState(); + if (isMobile) { + return; + } + e.preventDefault(); + e.stopPropagation(); + toggleBottomTerminal(); + return; + } + + if (eventMatchesShortcut(e, combo('toggle_terminal_expanded'))) { + const { isMobile, isBottomTerminalExpanded } = useUIStore.getState(); + if (isMobile) { + return; + } + e.preventDefault(); + e.stopPropagation(); + setBottomTerminalExpanded(!isBottomTerminalExpanded); + return; + } + }; const handleKeyDown = (e: KeyboardEvent) => { if (eventMatchesShortcut(e, combo('open_command_palette'))) { @@ -416,9 +454,11 @@ export const useKeyboardShortcuts = () => { } }; + window.addEventListener('keydown', handleTerminalShortcutCapture, true); window.addEventListener('keydown', handleKeyDown); return () => { + window.removeEventListener('keydown', handleTerminalShortcutCapture, true); window.removeEventListener('keydown', handleKeyDown); }; }, [