From 28f6d22f8dcf04a7c90777351a0b8638047b8b54 Mon Sep 17 00:00:00 2001 From: maria-rcks Date: Wed, 1 Jul 2026 15:46:22 -0400 Subject: [PATCH] feat(web): open terminal in right panel with shortcut Cmd+J routes to the right panel when it is open: closes the panel if a terminal tab is active, activates an existing terminal tab, or creates one. The bottom drawer keeps the shortcut while its terminal has focus, and drawer behavior is unchanged when the panel is closed. Co-Authored-By: Claude Fable 5 --- apps/web/src/components/ChatView.tsx | 38 +++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/apps/web/src/components/ChatView.tsx b/apps/web/src/components/ChatView.tsx index 8b1d2c672ba..86888d53573 100644 --- a/apps/web/src/components/ChatView.tsx +++ b/apps/web/src/components/ChatView.tsx @@ -2929,6 +2929,39 @@ function ChatViewContent(props: ChatViewProps) { }, [activeThreadRef, diffOpen, dismissPlanSidebarForCurrentTurn, onDiffPanelOpen, planSidebarOpen], ); + // Returns false when the right panel is closed so terminal.toggle falls back to the drawer. + const toggleTerminalInRightPanel = useCallback(() => { + if (!activeThreadRef) return false; + const store = useRightPanelStore.getState(); + const panelState = selectThreadRightPanelState(store.byThreadKey, activeThreadRef); + if (!panelState.isOpen) return false; + const activeSurface = panelState.surfaces.find( + (surface) => surface.id === panelState.activeSurfaceId, + ); + if (activeSurface?.kind === "terminal") { + setMaximizedRightPanelThreadKey(null); + store.close(activeThreadRef); + return true; + } + const terminalSurface = panelState.surfaces.find((surface) => surface.kind === "terminal"); + if (terminalSurface) { + activateRightPanelSurface(terminalSurface); + return true; + } + if (!activeThreadId || !activeProject) return false; + if (activeSurface?.kind === "plan") { + dismissPlanSidebarForCurrentTurn(); + } + addTerminalSurface(); + return true; + }, [ + activeProject, + activeThreadId, + activeThreadRef, + activateRightPanelSurface, + addTerminalSurface, + dismissPlanSidebarForCurrentTurn, + ]); const toggleRightPanel = useCallback(() => { if (!activeThreadRef) return; if (rightPanelOpen) { @@ -3725,7 +3758,9 @@ function ChatViewContent(props: ChatViewProps) { if (command === "terminal.toggle") { event.preventDefault(); event.stopPropagation(); - toggleTerminalVisibility(); + if (terminalFocusOwner === "drawer" || !toggleTerminalInRightPanel()) { + toggleTerminalVisibility(); + } return; } @@ -3838,6 +3873,7 @@ function ChatViewContent(props: ChatViewProps) { keybindings, onToggleDiff, toggleRightPanel, + toggleTerminalInRightPanel, toggleThreadPanel, toggleTerminalVisibility, composerRef,