From a65bfc6546253da1875949d0f0c623dfaa0f9c7c Mon Sep 17 00:00:00 2001 From: bradgroux Date: Mon, 7 Sep 2026 17:49:19 -0500 Subject: [PATCH] fix: preserve task navigation when compact layout closes chat --- .../__tests__/desktop-shell-context.test.tsx | 27 +++++++++++++++++++ .../components/layout/DesktopShellContext.tsx | 10 ++++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/web/src/__tests__/desktop-shell-context.test.tsx b/web/src/__tests__/desktop-shell-context.test.tsx index a28a38b8..9cce2b67 100644 --- a/web/src/__tests__/desktop-shell-context.test.tsx +++ b/web/src/__tests__/desktop-shell-context.test.tsx @@ -153,6 +153,33 @@ describe('desktop shell recovery', () => { expect(window.localStorage.getItem('veritas.desktop.rightRailOpen')).toBe('false'); }); + it('keeps the task history and focus when resize collapses the chat behind it', async () => { + const user = userEvent.setup(); + render( + + + + ); + await user.click(screen.getByRole('button', { name: 'Open board chat' })); + const taskState = { ...window.history.state, veritasTaskDetail: 'task-open-above-chat' }; + window.history.pushState(taskState, '', '/'); + const taskControl = screen.getByRole('button', { name: 'Reset layout' }); + taskControl.focus(); + const back = vi.spyOn(window.history, 'back').mockImplementation(() => {}); + try { + Object.defineProperty(window, 'innerWidth', { configurable: true, value: 1180 }); + act(() => window.dispatchEvent(new Event('resize'))); + expect(screen.getByLabelText('bottom panel').textContent).toBe('closed'); + expect(window.history.state.veritasTaskDetail).toBe('task-open-above-chat'); + expect(window.history.state.veritasBottomPanel).toBeUndefined(); + expect(back).not.toHaveBeenCalled(); + await new Promise((resolve) => requestAnimationFrame(() => resolve())); + expect(document.activeElement).toBe(taskControl); + } finally { + back.mockRestore(); + } + }); + it('minimizes both sidebars before opening Workbench at compact width', async () => { const user = userEvent.setup(); Object.defineProperty(window, 'innerWidth', { configurable: true, value: 1180 }); diff --git a/web/src/components/layout/DesktopShellContext.tsx b/web/src/components/layout/DesktopShellContext.tsx index 44d23c1c..f0eed9d8 100644 --- a/web/src/components/layout/DesktopShellContext.tsx +++ b/web/src/components/layout/DesktopShellContext.tsx @@ -314,7 +314,15 @@ export function DesktopShellProvider({ children }: { children: ReactNode }) { setRightRailOpenState(false); writeStoredValue(LEFT_RAIL_STORAGE_KEY, 'false'); writeStoredValue(RIGHT_RAIL_STORAGE_KEY, 'false'); - if (bottomPanel) closeBottomPanel(); + if (bottomPanel) { + // A layout collapse is not navigation: a task opened above the dock + // inherits its history marker. Going Back would dismiss that task. + setBottomPanel(null); + removeStoredValue(BOTTOM_PANEL_STORAGE_KEY); + panelTriggerRef.current = null; + const { [BOTTOM_PANEL_HISTORY_STATE_KEY]: _panel, ...rest } = window.history.state ?? {}; + window.history.replaceState(rest, '', window.location.href); + } }; window.addEventListener('keydown', handleKeyDown, true);