Files
twenty/packages/twenty-front/src/modules/ui/utilities/focus/hooks/usePushFocusItemToFocusStack.ts
Raphaël Bosi 1ab51d41aa Replace hotkey scopes by focus stack (Part 2 - Record Table, Rows and Cells) (#12798)
# Replace hotkey scopes by focus stack (Part 2 - Record Table, Rows and
Cells)

This PR is the second part of a refactoring aiming to deprecate the
hotkey scopes api in favor of the new focus stack api which is more
robust.
Part 1: https://github.com/twentyhq/twenty/pull/12673

The record table shortcuts are no longer centralized in the record
table, they now split and the focused element is in charge of applying
the desired shortcuts. (For instance: The rows are in charge of the row
navigation and the cells of the cells navigation).

## Video QA:


https://github.com/user-attachments/assets/f0bb9eed-8a2a-4b6d-a82f-1998e929f122


## Bugfixes:

### Fix record table click outside not working after opening and closing
a cell

Introduced by https://github.com/twentyhq/twenty/pull/11644

#### Before


https://github.com/user-attachments/assets/d28deda8-15e9-4ffe-b60a-e8b54625f8e5


#### After


https://github.com/user-attachments/assets/3f7e1ffc-15d9-4336-aeb0-bebd8ae0cbe0


### Fix ObjectFilterDropdownFilterInput hotkeys

Introduced by https://github.com/twentyhq/twenty/pull/12673

#### Before


https://github.com/user-attachments/assets/ab2039bd-ebe1-49ba-8377-a6b300664469


#### After


https://github.com/user-attachments/assets/90597453-dab2-426b-a134-0a24b0de0a6b
2025-06-25 13:18:51 +00:00

94 lines
3.1 KiB
TypeScript

import { DEBUG_FOCUS_STACK } from '@/ui/utilities/focus/constants/DebugFocusStack';
import { focusStackState } from '@/ui/utilities/focus/states/focusStackState';
import { FocusComponentType } from '@/ui/utilities/focus/types/FocusComponentType';
import { FocusStackItem } from '@/ui/utilities/focus/types/FocusStackItem';
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
import { GlobalHotkeysConfig } from '@/ui/utilities/hotkey/types/GlobalHotkeysConfig';
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
import { useRecoilCallback } from 'recoil';
import { logDebug } from '~/utils/logDebug';
const addOrMoveItemToTheTopOfTheStack = ({
focusStackItem,
currentFocusStack,
}: {
focusStackItem: FocusStackItem;
currentFocusStack: FocusStackItem[];
}) => [
...currentFocusStack.filter(
(currentFocusStackItem) =>
currentFocusStackItem.focusId !== focusStackItem.focusId,
),
focusStackItem,
];
export const usePushFocusItemToFocusStack = () => {
const { setHotkeyScopeAndMemorizePreviousScope } = usePreviousHotkeyScope();
const pushFocusItemToFocusStack = useRecoilCallback(
({ snapshot, set }) =>
({
focusId,
component,
hotkeyScope,
memoizeKey = 'global',
globalHotkeysConfig,
}: {
focusId: string;
component: {
type: FocusComponentType;
instanceId: string;
};
globalHotkeysConfig?: Partial<GlobalHotkeysConfig>;
// TODO: Remove this once we've migrated hotkey scopes to the new api
hotkeyScope: HotkeyScope;
memoizeKey?: string;
}) => {
const focusStackItem: FocusStackItem = {
focusId,
componentInstance: {
componentType: component.type,
componentInstanceId: component.instanceId,
},
globalHotkeysConfig: {
enableGlobalHotkeysWithModifiers:
globalHotkeysConfig?.enableGlobalHotkeysWithModifiers ?? true,
enableGlobalHotkeysConflictingWithKeyboard:
globalHotkeysConfig?.enableGlobalHotkeysConflictingWithKeyboard ??
true,
},
// TODO: Remove this once we've migrated hotkey scopes to the new api
memoizeKey,
};
const currentFocusStack = snapshot
.getLoadable(focusStackState)
.getValue();
const newFocusStack = addOrMoveItemToTheTopOfTheStack({
focusStackItem,
currentFocusStack,
});
set(focusStackState, newFocusStack);
if (DEBUG_FOCUS_STACK) {
logDebug(`DEBUG: pushFocusItemToFocusStack ${focusId}`, {
focusStackItem,
newFocusStack,
});
}
// TODO: Remove this once we've migrated hotkey scopes to the new api
setHotkeyScopeAndMemorizePreviousScope({
scope: hotkeyScope.scope,
customScopes: hotkeyScope.customScopes,
memoizeKey,
});
},
[setHotkeyScopeAndMemorizePreviousScope],
);
return { pushFocusItemToFocusStack };
};