From c3a9400f35107fdc5ce3bbc513daa5919cd2b339 Mon Sep 17 00:00:00 2001 From: lucaronin Date: Wed, 8 Apr 2026 21:05:16 +0200 Subject: [PATCH] fix: make AI panel shortcut command-only --- src/hooks/appKeyboardShortcuts.ts | 25 ++++++++++++++++++------- src/hooks/useAppKeyboard.test.ts | 8 ++++++++ 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/hooks/appKeyboardShortcuts.ts b/src/hooks/appKeyboardShortcuts.ts index 752b3d09..1d4c05b6 100644 --- a/src/hooks/appKeyboardShortcuts.ts +++ b/src/hooks/appKeyboardShortcuts.ts @@ -42,12 +42,16 @@ function isTextInputFocused(): boolean { return tag === 'INPUT' || tag === 'TEXTAREA' } -function isCmdOnly(e: KeyboardEvent): boolean { +function isCommandOrCtrlOnly(e: KeyboardEvent): boolean { return (e.metaKey || e.ctrlKey) && e.altKey === false } -function isCmdShiftOnly(e: KeyboardEvent): boolean { - return isCmdOnly(e) && e.shiftKey +function isCommandOrCtrlShiftOnly(e: KeyboardEvent): boolean { + return isCommandOrCtrlOnly(e) && e.shiftKey +} + +function isCommandShiftOnly(e: KeyboardEvent): boolean { + return e.metaKey && e.ctrlKey === false && e.altKey === false && e.shiftKey } function withActiveTab( @@ -86,7 +90,6 @@ export function createCommandKeyMap(actions: KeyboardActions): ShortcutMap { export function createShiftCommandKeyMap(actions: KeyboardActions): ShortcutMap { return { - l: () => actions.onToggleAIChat?.(), f: () => { trackEvent('search_used') actions.onSearch() @@ -97,7 +100,7 @@ export function createShiftCommandKeyMap(actions: KeyboardActions): ShortcutMap } export function handleViewModeKey(e: KeyboardEvent, onSetViewMode: (mode: ViewMode) => void): boolean { - if (isCmdOnly(e) === false || e.shiftKey) return false + if (isCommandOrCtrlOnly(e) === false || e.shiftKey) return false const mode = VIEW_MODE_KEYS[e.key] if (mode === undefined) return false e.preventDefault() @@ -106,7 +109,7 @@ export function handleViewModeKey(e: KeyboardEvent, onSetViewMode: (mode: ViewMo } export function handleCommandKey(e: KeyboardEvent, keyMap: ShortcutMap): boolean { - if (isCmdOnly(e) === false || e.shiftKey) return false + if (isCommandOrCtrlOnly(e) === false || e.shiftKey) return false const handler = keyMap[e.key] if (handler === undefined) return false if (TEXT_EDITING_KEYS.has(e.key) && isTextInputFocused()) return false @@ -115,8 +118,15 @@ export function handleCommandKey(e: KeyboardEvent, keyMap: ShortcutMap): boolean return true } +export function handleAiPanelKey(e: KeyboardEvent, onToggleAIChat?: () => void): boolean { + if (isCommandShiftOnly(e) === false || e.key.toLowerCase() !== 'l' || onToggleAIChat === undefined) return false + e.preventDefault() + onToggleAIChat() + return true +} + export function handleShiftCommandKey(e: KeyboardEvent, keyMap: ShortcutMap): boolean { - if (isCmdShiftOnly(e) === false) return false + if (isCommandOrCtrlShiftOnly(e) === false) return false const handler = keyMap[e.key.toLowerCase()] if (handler === undefined) return false e.preventDefault() @@ -125,6 +135,7 @@ export function handleShiftCommandKey(e: KeyboardEvent, keyMap: ShortcutMap): bo } export function handleAppKeyboardEvent(actions: KeyboardActions, event: KeyboardEvent) { + if (handleAiPanelKey(event, actions.onToggleAIChat)) return const shiftKeyMap = createShiftCommandKeyMap(actions) if (handleShiftCommandKey(event, shiftKeyMap)) return if (handleViewModeKey(event, actions.onSetViewMode)) return diff --git a/src/hooks/useAppKeyboard.test.ts b/src/hooks/useAppKeyboard.test.ts index a1b00072..8cc2b654 100644 --- a/src/hooks/useAppKeyboard.test.ts +++ b/src/hooks/useAppKeyboard.test.ts @@ -201,6 +201,14 @@ describe('useAppKeyboard', () => { }) }) + it('Ctrl+Shift+L does not trigger toggle AI chat', () => { + const actions = makeActions() + const onToggleAIChat = vi.fn() + renderHook(() => useAppKeyboard({ ...actions, onToggleAIChat })) + fireKey('l', { ctrlKey: true, shiftKey: true }) + expect(onToggleAIChat).not.toHaveBeenCalled() + }) + it('Cmd+I does not trigger AI chat (reserved for italic)', () => { const actions = makeActions() const onToggleAIChat = vi.fn()