From 176e81cd76e59f7c44be87f39b48a5365bf78441 Mon Sep 17 00:00:00 2001 From: BugIsGod <87571967+bugisthegod@users.noreply.github.com> Date: Tue, 31 Mar 2026 12:29:03 +0100 Subject: [PATCH] fix: clear navigation stack immediately in goBackFromSidePanel (#19153) Fixes: #19152 ## Summary goBackFromSidePanel returned early without writing the new (empty) stack to the store, leaving stale navigation state. And it caused openRecordInSidePanel to think the record was already open and skip reopening. image ## Before https://github.com/user-attachments/assets/03d1e24a-6d1e-4efc-93c1-72be0bc31a89 ## After When close the side panel with Escape, now it can be opened by clicking arrow button again. https://github.com/user-attachments/assets/ae700d41-4f81-4d1a-af9a-f97f31f489a6 --------- Co-authored-by: Devessier --- .../__tests__/useSidePanelHistory.test.tsx | 33 ++++++++++++++++++- .../side-panel/hooks/useSidePanelHistory.ts | 4 +-- .../side-panel/hooks/useSidePanelMenu.ts | 2 ++ 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/packages/twenty-front/src/modules/side-panel/hooks/__tests__/useSidePanelHistory.test.tsx b/packages/twenty-front/src/modules/side-panel/hooks/__tests__/useSidePanelHistory.test.tsx index 2a1e7238c3..470dad55f5 100644 --- a/packages/twenty-front/src/modules/side-panel/hooks/__tests__/useSidePanelHistory.test.tsx +++ b/packages/twenty-front/src/modules/side-panel/hooks/__tests__/useSidePanelHistory.test.tsx @@ -100,10 +100,13 @@ describe('useSidePanelHistory', () => { act(() => { result.current.commandMenuHistory.goBackFromSidePanel(); - result.current.sidePanelCloseAnimationCompleteCleanup.sidePanelCloseAnimationCompleteCleanup(); }); expect(jotaiStore.get(sidePanelNavigationStackState.atom)).toEqual([]); + + act(() => { + result.current.sidePanelCloseAnimationCompleteCleanup.sidePanelCloseAnimationCompleteCleanup(); + }); expect(jotaiStore.get(sidePanelPageState.atom)).toBe( SidePanelPages.CommandMenuDisplay, ); @@ -115,6 +118,34 @@ describe('useSidePanelHistory', () => { expect(jotaiStore.get(isSidePanelOpenedState.atom)).toBe(false); }); + it('should clear navigation stack immediately when closeSidePanelMenu is called', () => { + const { result } = renderHooks(); + + act(() => { + result.current.commandMenu.navigateSidePanelMenu({ + page: SidePanelPages.ViewRecord, + pageTitle: 'Company', + pageIcon: IconList, + pageId: '1', + }); + }); + + expect(jotaiStore.get(sidePanelNavigationStackState.atom)).toEqual([ + { + page: SidePanelPages.ViewRecord, + pageTitle: 'Company', + pageIcon: IconList, + pageId: '1', + }, + ]); + + act(() => { + result.current.commandMenu.closeSidePanelMenu(); + }); + + expect(jotaiStore.get(sidePanelNavigationStackState.atom)).toEqual([]); + }); + it('should navigate to a page in history', () => { const { result } = renderHooks(); diff --git a/packages/twenty-front/src/modules/side-panel/hooks/useSidePanelHistory.ts b/packages/twenty-front/src/modules/side-panel/hooks/useSidePanelHistory.ts index 7366c45409..233a9e1185 100644 --- a/packages/twenty-front/src/modules/side-panel/hooks/useSidePanelHistory.ts +++ b/packages/twenty-front/src/modules/side-panel/hooks/useSidePanelHistory.ts @@ -67,6 +67,8 @@ export const useSidePanelHistory = () => { const newNavigationStack = currentNavigationStack.slice(0, -1); const lastNavigationStackItem = newNavigationStack.at(-1); + store.set(sidePanelNavigationStackState.atom, newNavigationStack); + if (!isDefined(lastNavigationStackItem)) { closeSidePanelMenu(); return; @@ -80,8 +82,6 @@ export const useSidePanelHistory = () => { instanceId: lastNavigationStackItem.pageId, }); - store.set(sidePanelNavigationStackState.atom, newNavigationStack); - store.set(hasUserSelectedSidePanelListItemState.atom, false); }, [cleanupCurrentPage, closeSidePanelMenu, store]); diff --git a/packages/twenty-front/src/modules/side-panel/hooks/useSidePanelMenu.ts b/packages/twenty-front/src/modules/side-panel/hooks/useSidePanelMenu.ts index fd43638e0d..4a6ff8f544 100644 --- a/packages/twenty-front/src/modules/side-panel/hooks/useSidePanelMenu.ts +++ b/packages/twenty-front/src/modules/side-panel/hooks/useSidePanelMenu.ts @@ -3,6 +3,7 @@ import { selectedNavigationMenuItemIdInEditModeState } from '@/navigation-menu-i import { SIDE_PANEL_FOCUS_ID } from '@/side-panel/constants/SidePanelFocusId'; import { useNavigateSidePanel } from '@/side-panel/hooks/useNavigateSidePanel'; import { isSidePanelClosingState } from '@/side-panel/states/isSidePanelClosingState'; +import { sidePanelNavigationStackState } from '@/side-panel/states/sidePanelNavigationStackState'; import { isSidePanelOpenedState } from '@/side-panel/states/isSidePanelOpenedState'; import { sidePanelSearchObjectFilterState } from '@/side-panel/states/sidePanelSearchObjectFilterState'; import { sidePanelSearchState } from '@/side-panel/states/sidePanelSearchState'; @@ -28,6 +29,7 @@ export const useSidePanelMenu = () => { const isSidePanelOpened = store.get(isSidePanelOpenedState.atom); if (isSidePanelOpened) { + store.set(sidePanelNavigationStackState.atom, []); store.set(isSidePanelOpenedState.atom, false); store.set(isSidePanelClosingState.atom, true); closeAnyOpenDropdown();