Fixed global hotkey conflict in inputs (#13209)

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 <raphael.bosi@gmail.com>
Co-authored-by: Raphaël Bosi <71827178+bosiraphael@users.noreply.github.com>
This commit is contained in:
Lucas Bordeau
2025-07-15 14:18:06 +02:00
committed by GitHub
parent d916ec0af9
commit df9d2b57f9
4 changed files with 42 additions and 33 deletions

View File

@ -43,41 +43,41 @@ export const useCommandMenuHotKeys = () => {
COMMAND_MENU_COMPONENT_INSTANCE_ID, COMMAND_MENU_COMPONENT_INSTANCE_ID,
); );
useGlobalHotkeys( useGlobalHotkeys({
'ctrl+k,meta+k', keys: ['ctrl+k', 'meta+k'],
() => { callback: () => {
closeKeyboardShortcutMenu(); closeKeyboardShortcutMenu();
toggleCommandMenu(); toggleCommandMenu();
}, },
true, containsModifier: true,
[closeKeyboardShortcutMenu, toggleCommandMenu], dependencies: [closeKeyboardShortcutMenu, toggleCommandMenu],
); });
useGlobalHotkeys( useGlobalHotkeys({
['/'], keys: ['/'],
() => { callback: () => {
openRecordsSearchPage(); openRecordsSearchPage();
}, },
false, containsModifier: false,
[openRecordsSearchPage], dependencies: [openRecordsSearchPage],
{ options: {
ignoreModifiers: true, ignoreModifiers: true,
}, },
); });
useGlobalHotkeys( useGlobalHotkeys({
['@'], keys: ['@'],
() => { callback: () => {
if (isAiEnabled) { if (isAiEnabled) {
openAskAIPage(); openAskAIPage();
} }
}, },
false, containsModifier: false,
[openAskAIPage, isAiEnabled], dependencies: [openAskAIPage, isAiEnabled],
{ options: {
ignoreModifiers: true, ignoreModifiers: true,
}, },
); });
useHotkeysOnFocusedElement({ useHotkeysOnFocusedElement({
keys: [Key.Escape], keys: [Key.Escape],

View File

@ -15,15 +15,15 @@ export const KeyboardShortcutMenu = () => {
); );
const { closeCommandMenu } = useCommandMenu(); const { closeCommandMenu } = useCommandMenu();
useGlobalHotkeys( useGlobalHotkeys({
'shift+?,meta+?', keys: ['shift+?', 'meta+?'],
() => { callback: () => {
closeCommandMenu(); closeCommandMenu();
toggleKeyboardShortcutMenu(); toggleKeyboardShortcutMenu();
}, },
true, containsModifier: false,
[toggleKeyboardShortcutMenu], dependencies: [toggleKeyboardShortcutMenu],
); });
return ( return (
<>{isKeyboardShortcutMenuOpened && <KeyboardShortcutMenuOpenContent />}</> <>{isKeyboardShortcutMenuOpened && <KeyboardShortcutMenuOpenContent />}</>

View File

@ -66,6 +66,9 @@ export const RecordTitleFullNameFieldDisplay = ({
type: FocusComponentType.OPENED_FIELD_INPUT, type: FocusComponentType.OPENED_FIELD_INPUT,
instanceId: recordTitleCellId, instanceId: recordTitleCellId,
}, },
globalHotkeysConfig: {
enableGlobalHotkeysConflictingWithKeyboard: false,
},
}); });
openInlineCell(); openInlineCell();

View File

@ -7,13 +7,19 @@ import { isDefined } from 'twenty-shared/utils';
type UseHotkeysOptionsWithoutBuggyOptions = Omit<Options, 'enabled'>; type UseHotkeysOptionsWithoutBuggyOptions = Omit<Options, 'enabled'>;
export const useGlobalHotkeys = ( export const useGlobalHotkeys = ({
keys: Keys, keys,
callback: HotkeyCallback, callback,
containsModifier: boolean, containsModifier,
dependencies?: unknown[], dependencies,
options?: UseHotkeysOptionsWithoutBuggyOptions, options,
) => { }: {
keys: Keys;
callback: HotkeyCallback;
containsModifier: boolean;
dependencies?: unknown[];
options?: UseHotkeysOptionsWithoutBuggyOptions;
}) => {
const callGlobalHotkeysCallback = useGlobalHotkeysCallback(dependencies); const callGlobalHotkeysCallback = useGlobalHotkeysCallback(dependencies);
const enableOnContentEditable = isDefined(options?.enableOnContentEditable) const enableOnContentEditable = isDefined(options?.enableOnContentEditable)