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.
## 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();