diff --git a/components/settings/__tests__/settings-phone-deep-link.test.tsx b/components/settings/__tests__/settings-phone-deep-link.test.tsx index 80f8e963f..891eabe6d 100644 --- a/components/settings/__tests__/settings-phone-deep-link.test.tsx +++ b/components/settings/__tests__/settings-phone-deep-link.test.tsx @@ -102,6 +102,37 @@ describe('Settings deep links on the phone', () => { expect(screen.getByText('appearance pane')).toBeTruthy(); }); + it('adds one history entry however often the window crosses the phone breakpoint', () => { + window.history.replaceState(null, '', '/settings'); + media.desktop = true; + const { rerender } = render(); + const push = vi.spyOn(window.history, 'pushState'); + const resize = (desktop: boolean) => { + media.desktop = desktop; + rerender(); + }; + + resize(false); + expect(push).toHaveBeenCalledTimes(1); + resize(true); + resize(false); + resize(true); + resize(false); + expect(push).toHaveBeenCalledTimes(1); + expect(screen.getByText('appearance pane')).toBeTruthy(); + + // Back from the page lands on the list... + act(() => { + window.history.replaceState(null, '', '/settings'); + window.dispatchEvent(new PopStateEvent('popstate')); + }); + expect(screen.getByTestId('settings-tab-organize')).toBeTruthy(); + + // ...and a page opened from there has a Back of its own. + fireEvent.click(screen.getByTestId('settings-tab-organize')); + expect(push).toHaveBeenCalledTimes(2); + }); + it('opens a page at its top and keeps the place in the list', () => { window.history.replaceState(null, '', '/settings'); render(); diff --git a/components/settings/settings-app.tsx b/components/settings/settings-app.tsx index dff751d71..a3ff3f826 100644 --- a/components/settings/settings-app.tsx +++ b/components/settings/settings-app.tsx @@ -517,7 +517,12 @@ export function SettingsApp({ linkSegments: routeSegments }: SettingsAppProps = window.history.replaceState(window.history.state, '', listPath); } } - window.history.pushState({ __settingsSubmenu: true }, ''); + // Once per open page: this runs again each time the window crosses the + // phone breakpoint, and the entry from the last crossing is still there. + // Back leaves that entry, so opening a page afterwards adds a new one. + if (!(window.history.state as { __settingsSubmenu?: boolean } | null)?.__settingsSubmenu) { + window.history.pushState({ __settingsSubmenu: true }, ''); + } const handlePop = () => { setMobileShowContent(false);