Sync command menu with main context store (#19650)

## PR description

- The command menu in the side panel now reads directly from
`MAIN_CONTEXT_STORE_INSTANCE_ID` instead of snapshotting the main
context store into a separate side-panel instance when opening. This
keeps the command menu always in sync with the current page state
(selection, filters, view, etc.).
- Removed the broadening/reset-to-selection feature (Backspace to clear
context, "Reset to" button) since the command menu no longer maintains
its own copy of the context.

## Video QA


https://github.com/user-attachments/assets/5d5bc664-b6d4-431d-a271-6ce23d8a4ae0
This commit is contained in:
Raphaël Bosi
2026-04-13 18:08:15 +02:00
committed by GitHub
parent 123d6241d7
commit fb772c7695
19 changed files with 17 additions and 1144 deletions
@@ -4,20 +4,14 @@ import { PINNED_COMMAND_MENU_ITEMS_GAP } from '@/command-menu-item/display/const
import { commandMenuPinnedInlineLayoutState } from '@/command-menu-item/display/states/commandMenuPinnedInlineLayoutState';
import { getVisibleCommandMenuItemCountForContainerWidth } from '@/command-menu-item/display/utils/getVisibleCommandMenuItemCountForContainerWidth';
import { groupCommandMenuItems } from '@/command-menu-item/utils/groupCommandMenuItems';
import { contextStoreCurrentObjectMetadataItemIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemIdComponentState';
import { SidePanelGroup } from '@/side-panel/components/SidePanelGroup';
import { SidePanelList } from '@/side-panel/components/SidePanelList';
import { SIDE_PANEL_PREVIOUS_COMPONENT_INSTANCE_ID } from '@/side-panel/constants/SidePanelPreviousComponentInstanceId';
import { SIDE_PANEL_RESET_CONTEXT_TO_SELECTION } from '@/side-panel/constants/SidePanelResetContextToSelection';
import { SidePanelResetContextToSelectionButton } from '@/side-panel/pages/root/components/SidePanelResetContextToSelectionButton';
import { useFilterCommandMenuItemsWithSidePanelSearch } from '@/side-panel/pages/root/hooks/useFilterCommandMenuItemsWithSidePanelSearch';
import { sidePanelSearchState } from '@/side-panel/states/sidePanelSearchState';
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
import { useLingui } from '@lingui/react/macro';
import { isNumber } from '@sniptt/guards';
import { useContext, useMemo } from 'react';
import { isDefined } from 'twenty-shared/utils';
import { CommandMenuItemAvailabilityType } from '~/generated-metadata/graphql';
export const SidePanelCommandMenuItemDisplayPage = () => {
@@ -99,24 +93,8 @@ export const SidePanelCommandMenuItemDisplayPage = () => {
...(noResults ? fallbackCommandMenuItems : []),
].map((item) => item.id);
// oxlint-disable-next-line twenty/matching-state-variable
const previousContextStoreCurrentObjectMetadataItemId =
useAtomComponentStateValue(
contextStoreCurrentObjectMetadataItemIdComponentState,
SIDE_PANEL_PREVIOUS_COMPONENT_INSTANCE_ID,
);
if (isDefined(previousContextStoreCurrentObjectMetadataItemId)) {
selectableItemIds.unshift(SIDE_PANEL_RESET_CONTEXT_TO_SELECTION);
}
return (
<SidePanelList selectableItemIds={selectableItemIds} noResults={noResults}>
{isDefined(previousContextStoreCurrentObjectMetadataItemId) && (
<SidePanelGroup heading={t`Context`}>
<SidePanelResetContextToSelectionButton />
</SidePanelGroup>
)}
{matchingPinnedItems.length > 0 && (
<SidePanelGroup heading={t`Pinned`}>
{matchingPinnedItems.map((item) => (