From df9d2b57f9fc71853e771a418e13a8f2462375bb Mon Sep 17 00:00:00 2001 From: Lucas Bordeau Date: Tue, 15 Jul 2025 14:18:06 +0200 Subject: [PATCH] Fixed global hotkey conflict in inputs (#13209) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR fixes a focus conflict with global hotkeys, mainly "?" that opens the shortcut helper dialog. This fix works but we should maybe think about a more generic approach in another issue, like disabling global hotkeys when certain types of components are open (input, dropdown, etc.) Fixes https://github.com/twentyhq/twenty/issues/13197 --------- Co-authored-by: bosiraphael Co-authored-by: Raphaƫl Bosi <71827178+bosiraphael@users.noreply.github.com> --- .../hooks/useCommandMenuHotKeys.ts | 40 +++++++++---------- .../components/KeyboardShortcutMenu.tsx | 12 +++--- .../RecordTitleFullNameFieldDisplay.tsx | 3 ++ .../hotkey/hooks/useGlobalHotkeys.ts | 20 ++++++---- 4 files changed, 42 insertions(+), 33 deletions(-) diff --git a/packages/twenty-front/src/modules/command-menu/hooks/useCommandMenuHotKeys.ts b/packages/twenty-front/src/modules/command-menu/hooks/useCommandMenuHotKeys.ts index 5e5a8e5bf..881496624 100644 --- a/packages/twenty-front/src/modules/command-menu/hooks/useCommandMenuHotKeys.ts +++ b/packages/twenty-front/src/modules/command-menu/hooks/useCommandMenuHotKeys.ts @@ -43,41 +43,41 @@ export const useCommandMenuHotKeys = () => { COMMAND_MENU_COMPONENT_INSTANCE_ID, ); - useGlobalHotkeys( - 'ctrl+k,meta+k', - () => { + useGlobalHotkeys({ + keys: ['ctrl+k', 'meta+k'], + callback: () => { closeKeyboardShortcutMenu(); toggleCommandMenu(); }, - true, - [closeKeyboardShortcutMenu, toggleCommandMenu], - ); + containsModifier: true, + dependencies: [closeKeyboardShortcutMenu, toggleCommandMenu], + }); - useGlobalHotkeys( - ['/'], - () => { + useGlobalHotkeys({ + keys: ['/'], + callback: () => { openRecordsSearchPage(); }, - false, - [openRecordsSearchPage], - { + containsModifier: false, + dependencies: [openRecordsSearchPage], + options: { ignoreModifiers: true, }, - ); + }); - useGlobalHotkeys( - ['@'], - () => { + useGlobalHotkeys({ + keys: ['@'], + callback: () => { if (isAiEnabled) { openAskAIPage(); } }, - false, - [openAskAIPage, isAiEnabled], - { + containsModifier: false, + dependencies: [openAskAIPage, isAiEnabled], + options: { ignoreModifiers: true, }, - ); + }); useHotkeysOnFocusedElement({ keys: [Key.Escape], diff --git a/packages/twenty-front/src/modules/keyboard-shortcut-menu/components/KeyboardShortcutMenu.tsx b/packages/twenty-front/src/modules/keyboard-shortcut-menu/components/KeyboardShortcutMenu.tsx index a6463df60..d9ccbea01 100644 --- a/packages/twenty-front/src/modules/keyboard-shortcut-menu/components/KeyboardShortcutMenu.tsx +++ b/packages/twenty-front/src/modules/keyboard-shortcut-menu/components/KeyboardShortcutMenu.tsx @@ -15,15 +15,15 @@ export const KeyboardShortcutMenu = () => { ); const { closeCommandMenu } = useCommandMenu(); - useGlobalHotkeys( - 'shift+?,meta+?', - () => { + useGlobalHotkeys({ + keys: ['shift+?', 'meta+?'], + callback: () => { closeCommandMenu(); toggleKeyboardShortcutMenu(); }, - true, - [toggleKeyboardShortcutMenu], - ); + containsModifier: false, + dependencies: [toggleKeyboardShortcutMenu], + }); return ( <>{isKeyboardShortcutMenuOpened && } diff --git a/packages/twenty-front/src/modules/object-record/record-title-cell/components/RecordTitleFullNameFieldDisplay.tsx b/packages/twenty-front/src/modules/object-record/record-title-cell/components/RecordTitleFullNameFieldDisplay.tsx index 0a37942b3..87dec9fa9 100644 --- a/packages/twenty-front/src/modules/object-record/record-title-cell/components/RecordTitleFullNameFieldDisplay.tsx +++ b/packages/twenty-front/src/modules/object-record/record-title-cell/components/RecordTitleFullNameFieldDisplay.tsx @@ -66,6 +66,9 @@ export const RecordTitleFullNameFieldDisplay = ({ type: FocusComponentType.OPENED_FIELD_INPUT, instanceId: recordTitleCellId, }, + globalHotkeysConfig: { + enableGlobalHotkeysConflictingWithKeyboard: false, + }, }); openInlineCell(); diff --git a/packages/twenty-front/src/modules/ui/utilities/hotkey/hooks/useGlobalHotkeys.ts b/packages/twenty-front/src/modules/ui/utilities/hotkey/hooks/useGlobalHotkeys.ts index 5bcd9b7f5..f4fd7dca7 100644 --- a/packages/twenty-front/src/modules/ui/utilities/hotkey/hooks/useGlobalHotkeys.ts +++ b/packages/twenty-front/src/modules/ui/utilities/hotkey/hooks/useGlobalHotkeys.ts @@ -7,13 +7,19 @@ import { isDefined } from 'twenty-shared/utils'; type UseHotkeysOptionsWithoutBuggyOptions = Omit; -export const useGlobalHotkeys = ( - keys: Keys, - callback: HotkeyCallback, - containsModifier: boolean, - dependencies?: unknown[], - options?: UseHotkeysOptionsWithoutBuggyOptions, -) => { +export const useGlobalHotkeys = ({ + keys, + callback, + containsModifier, + dependencies, + options, +}: { + keys: Keys; + callback: HotkeyCallback; + containsModifier: boolean; + dependencies?: unknown[]; + options?: UseHotkeysOptionsWithoutBuggyOptions; +}) => { const callGlobalHotkeysCallback = useGlobalHotkeysCallback(dependencies); const enableOnContentEditable = isDefined(options?.enableOnContentEditable)