diff --git a/packages/twenty-front/src/modules/activities/components/ActivityRichTextEditor.tsx b/packages/twenty-front/src/modules/activities/components/ActivityRichTextEditor.tsx
index a9fa9a3e27..308d3c561a 100644
--- a/packages/twenty-front/src/modules/activities/components/ActivityRichTextEditor.tsx
+++ b/packages/twenty-front/src/modules/activities/components/ActivityRichTextEditor.tsx
@@ -344,7 +344,9 @@ export const ActivityRichTextEditor = ({
dependencies: [editor],
});
- const handleAllKeys = (keyboardEvent: KeyboardEvent) => {
+ const focusRichTextEditorWhenFocusOnSidePanel = (
+ keyboardEvent: KeyboardEvent,
+ ) => {
if (keyboardEvent.key === Key.Escape) {
return;
}
@@ -378,9 +380,9 @@ export const ActivityRichTextEditor = ({
useHotkeysOnFocusedElement({
keys: '*',
- callback: handleAllKeys,
+ callback: focusRichTextEditorWhenFocusOnSidePanel,
focusId: SIDE_PANEL_FOCUS_ID,
- dependencies: [handleAllKeys],
+ dependencies: [focusRichTextEditorWhenFocusOnSidePanel],
});
const { labelIdentifierFieldMetadataItem } =
@@ -431,7 +433,7 @@ export const ActivityRichTextEditor = ({
focusId: activityId,
globalHotkeysConfig: {
enableGlobalHotkeysConflictingWithKeyboard: false,
- enableGlobalHotkeysWithModifiers: false,
+ enableGlobalHotkeysWithModifiers: true,
},
});
},
diff --git a/packages/twenty-front/src/modules/command-menu/components/CommandMenuTopBar.tsx b/packages/twenty-front/src/modules/command-menu/components/CommandMenuTopBar.tsx
index 586106b1d1..f34c230b9c 100644
--- a/packages/twenty-front/src/modules/command-menu/components/CommandMenuTopBar.tsx
+++ b/packages/twenty-front/src/modules/command-menu/components/CommandMenuTopBar.tsx
@@ -5,12 +5,16 @@ import { CommandMenuTopBarRightCornerIcon } from '@/command-menu/components/Comm
import { COMMAND_MENU_SEARCH_BAR_HEIGHT } from '@/command-menu/constants/CommandMenuSearchBarHeight';
import { COMMAND_MENU_SEARCH_BAR_HEIGHT_MOBILE } from '@/command-menu/constants/CommandMenuSearchBarHeightMobile';
import { COMMAND_MENU_SEARCH_BAR_PADDING } from '@/command-menu/constants/CommandMenuSearchBarPadding';
+import { COMMAND_MENU_SEARCH_INPUT_FOCUS_ID } from '@/command-menu/constants/CommandMenuSearchInputFocusId';
import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
import { useCommandMenuContextChips } from '@/command-menu/hooks/useCommandMenuContextChips';
import { commandMenuNavigationStackState } from '@/command-menu/states/commandMenuNavigationStackState';
import { commandMenuPageState } from '@/command-menu/states/commandMenuPageState';
import { commandMenuSearchState } from '@/command-menu/states/commandMenuSearchState';
import { CommandMenuPages } from '@/command-menu/types/CommandMenuPages';
+import { usePushFocusItemToFocusStack } from '@/ui/utilities/focus/hooks/usePushFocusItemToFocusStack';
+import { useRemoveFocusItemFromFocusStackById } from '@/ui/utilities/focus/hooks/useRemoveFocusItemFromFocusStackById';
+import { FocusComponentType } from '@/ui/utilities/focus/types/FocusComponentType';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { useLingui } from '@lingui/react/macro';
@@ -100,6 +104,29 @@ export const CommandMenuTopBar = () => {
const { contextChips } = useCommandMenuContextChips();
+ const { pushFocusItemToFocusStack } = usePushFocusItemToFocusStack();
+ const { removeFocusItemFromFocusStackById } =
+ useRemoveFocusItemFromFocusStackById();
+
+ const handleInputFocus = () => {
+ pushFocusItemToFocusStack({
+ focusId: COMMAND_MENU_SEARCH_INPUT_FOCUS_ID,
+ component: {
+ type: FocusComponentType.TEXT_INPUT,
+ instanceId: COMMAND_MENU_SEARCH_INPUT_FOCUS_ID,
+ },
+ globalHotkeysConfig: {
+ enableGlobalHotkeysConflictingWithKeyboard: false,
+ },
+ });
+ };
+
+ const handleInputBlur = () => {
+ removeFocusItemFromFocusStackById({
+ focusId: COMMAND_MENU_SEARCH_INPUT_FOCUS_ID,
+ });
+ };
+
const canGoBack = commandMenuNavigationStack.length > 1;
const shouldShowCloseButton =
@@ -148,11 +175,13 @@ export const CommandMenuTopBar = () => {
commandMenuPage === CommandMenuPages.SearchRecords) && (
<>
>
diff --git a/packages/twenty-front/src/modules/command-menu/components/__stories__/CommandMenu.stories.tsx b/packages/twenty-front/src/modules/command-menu/components/__stories__/CommandMenu.stories.tsx
index c2a2855113..256f811f02 100644
--- a/packages/twenty-front/src/modules/command-menu/components/__stories__/CommandMenu.stories.tsx
+++ b/packages/twenty-front/src/modules/command-menu/components/__stories__/CommandMenu.stories.tsx
@@ -20,6 +20,7 @@ import { ActionMenuComponentInstanceContext } from '@/action-menu/states/context
import { currentUserWorkspaceState } from '@/auth/states/currentUserWorkspaceState';
import { CommandMenuRouter } from '@/command-menu/components/CommandMenuRouter';
import { COMMAND_MENU_COMPONENT_INSTANCE_ID } from '@/command-menu/constants/CommandMenuComponentInstanceId';
+import { COMMAND_MENU_SEARCH_INPUT_FOCUS_ID } from '@/command-menu/constants/CommandMenuSearchInputFocusId';
import { commandMenuNavigationStackState } from '@/command-menu/states/commandMenuNavigationStackState';
import { isCommandMenuOpenedState } from '@/command-menu/states/isCommandMenuOpenedState';
import { CommandMenuPages } from '@/command-menu/types/CommandMenuPages';
@@ -151,7 +152,9 @@ export const LimitedPermissions: Story = {
export const MatchingNavigate: Story = {
play: async () => {
const canvas = within(document.body);
- const searchInput = await canvas.findByTestId('command-menu-search-input');
+ const searchInput = await canvas.findByTestId(
+ COMMAND_MENU_SEARCH_INPUT_FOCUS_ID,
+ );
await sleep(openTimeout);
await userEvent.type(searchInput, 'ta');
expect(await canvas.findByText('Go to Tasks')).toBeVisible();
@@ -161,7 +164,9 @@ export const MatchingNavigate: Story = {
export const MatchingNavigateShortcuts: Story = {
play: async () => {
const canvas = within(document.body);
- const searchInput = await canvas.findByTestId('command-menu-search-input');
+ const searchInput = await canvas.findByTestId(
+ COMMAND_MENU_SEARCH_INPUT_FOCUS_ID,
+ );
await sleep(openTimeout);
await userEvent.type(searchInput, 'gp');
expect(await canvas.findByText('Go to People')).toBeVisible();
@@ -186,7 +191,9 @@ export const MatchingNavigateShortcuts: Story = {
export const NoResultsSearchFallback: Story = {
play: async () => {
const canvas = within(document.body);
- const searchInput = await canvas.findByTestId('command-menu-search-input');
+ const searchInput = await canvas.findByTestId(
+ COMMAND_MENU_SEARCH_INPUT_FOCUS_ID,
+ );
await sleep(openTimeout);
await userEvent.type(searchInput, 'input without results');
expect(await canvas.findByText('No results found')).toBeVisible();
diff --git a/packages/twenty-front/src/modules/command-menu/constants/CommandMenuSearchInputFocusId.ts b/packages/twenty-front/src/modules/command-menu/constants/CommandMenuSearchInputFocusId.ts
new file mode 100644
index 0000000000..35ce16675f
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu/constants/CommandMenuSearchInputFocusId.ts
@@ -0,0 +1 @@
+export const COMMAND_MENU_SEARCH_INPUT_FOCUS_ID = 'command-menu-search-input';
diff --git a/packages/twenty-front/src/modules/command-menu/hooks/useCommandMenu.ts b/packages/twenty-front/src/modules/command-menu/hooks/useCommandMenu.ts
index 9c0641b252..8ca678d8bd 100644
--- a/packages/twenty-front/src/modules/command-menu/hooks/useCommandMenu.ts
+++ b/packages/twenty-front/src/modules/command-menu/hooks/useCommandMenu.ts
@@ -2,6 +2,7 @@ import { useRecoilCallback } from 'recoil';
import { commandMenuSearchState } from '@/command-menu/states/commandMenuSearchState';
+import { COMMAND_MENU_SEARCH_INPUT_FOCUS_ID } from '@/command-menu/constants/CommandMenuSearchInputFocusId';
import { SIDE_PANEL_FOCUS_ID } from '@/command-menu/constants/SidePanelFocusId';
import { useNavigateCommandMenu } from '@/command-menu/hooks/useNavigateCommandMenu';
import { isCommandMenuClosingState } from '@/command-menu/states/isCommandMenuClosingState';
@@ -33,6 +34,9 @@ export const useCommandMenu = () => {
set(isCommandMenuClosingState, true);
set(isDragSelectionStartEnabledState, true);
closeAnyOpenDropdown();
+ removeFocusItemFromFocusStackById({
+ focusId: COMMAND_MENU_SEARCH_INPUT_FOCUS_ID,
+ });
removeFocusItemFromFocusStackById({
focusId: SIDE_PANEL_FOCUS_ID,
});