diff --git a/packages/ui/src/hooks/keyboard-shortcut-dom.test.ts b/packages/ui/src/hooks/keyboard-shortcut-dom.test.ts index f475c3ae..e967f7d4 100644 --- a/packages/ui/src/hooks/keyboard-shortcut-dom.test.ts +++ b/packages/ui/src/hooks/keyboard-shortcut-dom.test.ts @@ -1,6 +1,10 @@ import { expect, test } from 'bun:test'; +import { Window } from 'happy-dom'; -import { hasOpenDropdown, shouldStopDropdownImeEscape } from './keyboard-shortcut-dom'; +import { hasOpenDropdown, isEditableEventTarget, shouldStopDropdownImeEscape } from './keyboard-shortcut-dom'; + +const domWindow = new Window(); +Object.assign(globalThis, { document: domWindow.document, HTMLElement: domWindow.HTMLElement }); test('does not treat an unrelated visible listbox as an open dropdown', () => { const promptNavigator = {} as Element; @@ -35,3 +39,19 @@ test('stops IME Escape before an open dropdown dismiss listener', () => { expect(shouldStopDropdownImeEscape({ key: 'Escape', isComposing: false, keyCode: 27 }, true)).toBe(false); expect(shouldStopDropdownImeEscape({ key: 'Escape', isComposing: true, keyCode: 0 }, false)).toBe(false); }); + +test('treats inputs, textareas, selects, and contenteditable elements as editable targets', () => { + expect(isEditableEventTarget(document.createElement('input'))).toBe(true); + expect(isEditableEventTarget(document.createElement('textarea'))).toBe(true); + expect(isEditableEventTarget(document.createElement('select'))).toBe(true); + + const editableDiv = document.createElement('div'); + Object.defineProperty(editableDiv, 'isContentEditable', { value: true }); + expect(isEditableEventTarget(editableDiv)).toBe(true); +}); + +test('does not treat a plain element or non-element target as editable', () => { + expect(isEditableEventTarget(document.createElement('div'))).toBe(false); + expect(isEditableEventTarget(document.createElement('button'))).toBe(false); + expect(isEditableEventTarget(null)).toBe(false); +}); diff --git a/packages/ui/src/hooks/useKeyboardShortcuts.ts b/packages/ui/src/hooks/useKeyboardShortcuts.ts index 61ad272d..2549cbcd 100644 --- a/packages/ui/src/hooks/useKeyboardShortcuts.ts +++ b/packages/ui/src/hooks/useKeyboardShortcuts.ts @@ -493,6 +493,7 @@ export const useKeyboardShortcuts = () => { && !event.repeat && eventMatchesShortcutPrefix(event, switchSurfacePrefix, heldKeysRef.current) ) { + if (isEditableEventTarget(event.target)) return; const state = useUIStore.getState(); if (!state.isMobile && effectiveDirectory) { const directory = normalizeContextPanelDirectoryKey(effectiveDirectory);