diff --git a/apps/desktop/src/app/hooks/use-keybinds.ts b/apps/desktop/src/app/hooks/use-keybinds.ts index 8a30c3049ff1e..c9c5df71143f2 100644 --- a/apps/desktop/src/app/hooks/use-keybinds.ts +++ b/apps/desktop/src/app/hooks/use-keybinds.ts @@ -24,6 +24,7 @@ import { findPrevious as findPreviousMatch, openFindBar } from '@/store/find-in-page' +import { toggleHud } from '@/store/hud' import { $capture, $comboIndex, endCapture, setBinding } from '@/store/keybinds' import { requestSessionSearchFocus, @@ -227,6 +228,7 @@ export function useKeybinds(deps: KeybindRuntimeDeps): void { 'view.toggleReview': toggleReview, 'view.toggleStatusbar': toggleStatusbarVisible, 'view.showFiles': showFiles, + 'view.toggleHud': () => toggleHud($selectedStoredSessionId.get()), 'view.showTerminal': () => togglePaneVisible('terminal'), // Create first so the pane's open-effect ensure sees a non-empty set and // doesn't also spawn one — net effect is exactly one fresh terminal. diff --git a/apps/desktop/src/app/shell/titlebar-controls.tsx b/apps/desktop/src/app/shell/titlebar-controls.tsx index 6c3c3e5fc5fdb..9aa02aa67cce5 100644 --- a/apps/desktop/src/app/shell/titlebar-controls.tsx +++ b/apps/desktop/src/app/shell/titlebar-controls.tsx @@ -11,6 +11,8 @@ import { useI18n } from '@/i18n' import { triggerHaptic } from '@/lib/haptics' import { cn } from '@/lib/utils' import { $hapticsMuted, toggleHapticsMuted } from '@/store/haptics' +import { toggleHud } from '@/store/hud' +import { $selectedStoredSessionId } from '@/store/session' import { $fileBrowserOpen, $sidebarOpen, @@ -187,6 +189,20 @@ export function TitlebarControls({ leftTools = [], tools = [], onOpenSettings }: label: hapticsMuted ? t.titlebar.unmuteHaptics : t.titlebar.muteHaptics, onSelect: toggleHaptics }, + { + // No `title`: TitlebarToolButton passes `title` to TipKeybindLabel as a + // text OVERRIDE, so a long sentence there replaces the short label and + // crowds the ⌘⇧H hint off the tooltip. Label only — the hint is appended + // from the action registry, same as every other tool here. + actionId: 'view.toggleHud', + icon: , + id: 'hud', + label: t.titlebar.enterHud, + onSelect: () => { + triggerHaptic('open') + toggleHud($selectedStoredSessionId.get()) + } + }, { actionId: 'keybinds.openPanel', icon: , diff --git a/apps/desktop/src/i18n/ar.ts b/apps/desktop/src/i18n/ar.ts index 65ba2f448dddf..02e7229400b40 100644 --- a/apps/desktop/src/i18n/ar.ts +++ b/apps/desktop/src/i18n/ar.ts @@ -173,6 +173,8 @@ export const ar = defineLocale({ openSettings: 'فتح الإعدادات', openStarmap: 'فتح خريطة الذاكرة', openKeybinds: 'اختصارات لوحة المفاتيح', + enterHud: 'وضع HUD', + exitHud: 'إنهاء وضع HUD', layoutEditor: 'محرر التخطيط', layoutEditorTitle: 'محرر التخطيط — انقر مع ⌘ لإعادة ضبط التخطيط' }, diff --git a/apps/desktop/src/i18n/en.ts b/apps/desktop/src/i18n/en.ts index ee3eeed7df751..03ae6b5b2c403 100644 --- a/apps/desktop/src/i18n/en.ts +++ b/apps/desktop/src/i18n/en.ts @@ -203,6 +203,8 @@ export const en: Translations = { openSettings: 'Open settings', openStarmap: 'Open memory graph', openKeybinds: 'Keyboard shortcuts', + enterHud: 'HUD mode', + exitHud: 'Exit HUD mode', layoutEditor: 'Layout editor', layoutEditorTitle: 'Layout editor — ⌘-click resets the layout' }, @@ -261,6 +263,7 @@ export const en: Translations = { 'view.toggleReview': 'Toggle review pane', 'view.toggleStatusbar': 'Toggle status bar', 'view.showFiles': 'Show file browser', + 'view.toggleHud': 'Toggle HUD mode', 'view.showTerminal': 'Toggle terminal', 'view.newTerminal': 'New terminal', 'view.nextTerminal': 'Next terminal', diff --git a/apps/desktop/src/i18n/types.ts b/apps/desktop/src/i18n/types.ts index d29f3d38e0178..e9ca76d857bc0 100644 --- a/apps/desktop/src/i18n/types.ts +++ b/apps/desktop/src/i18n/types.ts @@ -245,6 +245,8 @@ export interface Translations { openSettings: string openStarmap: string openKeybinds: string + enterHud: string + exitHud: string layoutEditor: string layoutEditorTitle: string } diff --git a/apps/desktop/src/i18n/zh.ts b/apps/desktop/src/i18n/zh.ts index bb063e5752d35..e38735e7885e3 100644 --- a/apps/desktop/src/i18n/zh.ts +++ b/apps/desktop/src/i18n/zh.ts @@ -198,6 +198,8 @@ export const zh: Translations = { openSettings: '打开设置', openStarmap: '打开记忆图谱', openKeybinds: '键盘快捷键', + enterHud: 'HUD 模式', + exitHud: '退出 HUD 模式', layoutEditor: '布局编辑器', layoutEditorTitle: '布局编辑器 — ⌘ 点击重置布局' }, diff --git a/apps/desktop/src/lib/keybinds/actions.ts b/apps/desktop/src/lib/keybinds/actions.ts index 392292bd7c2f7..be2d9d1317674 100644 --- a/apps/desktop/src/lib/keybinds/actions.ts +++ b/apps/desktop/src/lib/keybinds/actions.ts @@ -116,6 +116,11 @@ export const KEYBIND_ACTIONS: readonly KeybindActionMeta[] = [ // ⌘G — "g" for git; the review pane is the source-control view. { id: 'view.toggleReview', category: 'view', defaults: ['mod+g'] }, { id: 'view.showFiles', category: 'view', defaults: [] }, + // ⌘⇧H — "h" for HUD. Enters/leaves the chrome-free floating chat: the app + // window steps aside and a composer + live reply float over whatever the + // user is working in. Ships bound because the whole point is leaving the app + // without reaching for it — but the titlebar button is the discoverable door. + { id: 'view.toggleHud', category: 'view', defaults: ['mod+shift+h'] }, // Control+` everywhere (literal `ctrl`, NOT `mod`): ⌘` is macOS-reserved for // cycling app windows, so VS Code/Cursor/Zed bind the terminal to Ctrl+` on // every platform. Off macOS `ctrl` folds to `mod` (= Ctrl), so it's unchanged.