Files
twenty/packages/twenty-front/src/modules/command-menu/hooks/useCommandMenu.ts
T
Charles Bochet 121788c42f Fully deprecate old recoil (#18210)
## Summary

Removes the `recoil` dependency entirely from `package.json` and
`twenty-front/package.json`, completing the migration to Jotai as the
sole state management library.

Removes all Recoil infrastructure: `RecoilRoot` wrapper from `App.tsx`
and test decorators, `RecoilDebugObserver`, Recoil-specific ESLint rules
(`use-getLoadable-and-getValue-to-get-atoms`,
`useRecoilCallback-has-dependency-array`), and legacy Recoil utility
hooks/types (`useRecoilComponentState`, `useRecoilComponentValue`,
`createComponentState`, `createFamilyState`, `getSnapshotValue`,
`cookieStorageEffect`, `localStorageEffect`, etc.).

Renames all `V2`-suffixed Jotai state files and types to their canonical
names (e.g., `ComponentStateV2` -> `ComponentState`,
`agentChatInputStateV2` -> `agentChatInputState`, `SelectorCallbacksV2`
-> `SelectorCallbacks`), and removes the now-redundant V1 counterparts.

Updates ~433 files across the codebase to use the renamed Jotai imports,
remove Recoil imports, and clean up test wrappers (`RecoilRootDecorator`
-> `JotaiRootDecorator`).
2026-02-25 12:26:42 +01:00

68 lines
2.6 KiB
TypeScript

import { SIDE_PANEL_FOCUS_ID } from '@/command-menu/constants/SidePanelFocusId';
import { useNavigateCommandMenu } from '@/command-menu/hooks/useNavigateCommandMenu';
import { commandMenuSearchState } from '@/command-menu/states/commandMenuSearchState';
import { isCommandMenuClosingState } from '@/command-menu/states/isCommandMenuClosingState';
import { isCommandMenuOpenedState } from '@/command-menu/states/isCommandMenuOpenedState';
import { addToNavPayloadRegistryState } from '@/navigation-menu-item/states/addToNavPayloadRegistryState';
import { useCloseAnyOpenDropdown } from '@/ui/layout/dropdown/hooks/useCloseAnyOpenDropdown';
import { emitSidePanelOpenEvent } from '@/ui/layout/right-drawer/utils/emitSidePanelOpenEvent';
import { useRemoveFocusItemFromFocusStackById } from '@/ui/utilities/focus/hooks/useRemoveFocusItemFromFocusStackById';
import { t } from '@lingui/core/macro';
import { useCallback } from 'react';
import { CommandMenuPages } from 'twenty-shared/types';
import { IconDotsVertical } from 'twenty-ui/display';
import { useStore } from 'jotai';
export const useCommandMenu = () => {
const store = useStore();
const { navigateCommandMenu } = useNavigateCommandMenu();
const { closeAnyOpenDropdown } = useCloseAnyOpenDropdown();
const { removeFocusItemFromFocusStackById } =
useRemoveFocusItemFromFocusStackById();
const closeCommandMenu = useCallback(() => {
const isCommandMenuOpened = store.get(isCommandMenuOpenedState.atom);
if (isCommandMenuOpened) {
store.set(addToNavPayloadRegistryState.atom, new Map());
store.set(isCommandMenuOpenedState.atom, false);
store.set(isCommandMenuClosingState.atom, true);
closeAnyOpenDropdown();
removeFocusItemFromFocusStackById({
focusId: SIDE_PANEL_FOCUS_ID,
});
}
}, [closeAnyOpenDropdown, removeFocusItemFromFocusStackById, store]);
const openCommandMenu = useCallback(() => {
emitSidePanelOpenEvent();
closeAnyOpenDropdown();
navigateCommandMenu({
page: CommandMenuPages.Root,
pageTitle: t`Command Menu`,
pageIcon: IconDotsVertical,
resetNavigationStack: true,
});
}, [closeAnyOpenDropdown, navigateCommandMenu]);
const toggleCommandMenu = useCallback(() => {
const isCommandMenuOpened = store.get(isCommandMenuOpenedState.atom);
store.set(commandMenuSearchState.atom, '');
if (isCommandMenuOpened) {
closeCommandMenu();
} else {
openCommandMenu();
}
}, [closeCommandMenu, openCommandMenu, store]);
return {
openCommandMenu,
closeCommandMenu,
navigateCommandMenu,
toggleCommandMenu,
};
};