From 84ee807be1f8fb00334a13028cebb310bd10c3b4 Mon Sep 17 00:00:00 2001 From: Michael Khabarov Date: Sat, 24 Oct 2026 16:22:51 -0300 Subject: [PATCH] fix(vue-router): reset tab after other tab reset Tapping the active tab resets it with router.go(). When another route is pushed after that, the browser drops every history entry after it, including the root of a tab whose child is pushed next. The first entry of that tab's stack is then ahead of the current position, so tapping the tab button called router.go() with a positive delta and nothing happened. Replace the current entry with the tab root in that case, as the tab already does when its first entry is the current one. Co-Authored-By: Claude Opus 5.5 --- packages/vue-router/src/router.ts | 15 ++++++++- .../base/tests/e2e/playwright/tabs.spec.ts | 31 +++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/packages/vue-router/src/router.ts b/packages/vue-router/src/router.ts index 95443549c9e..7fcc93b7cf4 100644 --- a/packages/vue-router/src/router.ts +++ b/packages/vue-router/src/router.ts @@ -848,10 +848,23 @@ export const createIonRouter = ( } return; } - if (delta !== 0) { + if (delta < 0) { router.go(delta); return; } + /** + * The first history entry for this tab is ahead of the current + * entry, so the browser dropped it when another route was pushed + * after going back, and router.go() has nothing to reach. Happens + * after resetting another tab with router.go() and then switching + * to this tab. Replace with `originalHref` instead. + */ + if (delta > 0) { + if (originalHref) { + handleNavigate(originalHref, "pop", "back", undefined, tab); + } + return; + } /** * The first history entry for this tab is the current entry, * so there's nothing earlier to traverse back to. Happens diff --git a/packages/vue/test/base/tests/e2e/playwright/tabs.spec.ts b/packages/vue/test/base/tests/e2e/playwright/tabs.spec.ts index eb5dc1f0a78..1aeea82a8ab 100644 --- a/packages/vue/test/base/tests/e2e/playwright/tabs.spec.ts +++ b/packages/vue/test/base/tests/e2e/playwright/tabs.spec.ts @@ -36,4 +36,35 @@ test.describe('Tabs', () => { await tabClick(page, 'tab1'); await ionPageVisible(page, 'tab1'); }); + + test('tab button should reset its tab after another tab was reset', async ({ page }) => { + await page.goto('/tabs/tab1'); + await ionPageVisible(page, 'tab1'); + + await page.locator('div.ion-page[data-pageid=tab1] #child-one').click(); + await ionPageVisible(page, 'tab1childone'); + + await tabClick(page, 'tab2'); + await ionPageVisible(page, 'tab2'); + + await page.locator('div.ion-page[data-pageid=tab2] #child-one').click(); + await ionPageVisible(page, 'tab2childone'); + + await tabClick(page, 'tab1'); + await ionPageVisible(page, 'tab1childone'); + + // Resetting tab1 goes back to its root via router.go(-4) + await tabClick(page, 'tab1'); + await ionPageVisible(page, 'tab1'); + await ionPageDoesNotExist(page, 'tab1childone'); + + // Pushing tab2's child drops the browser history entry of the tab2 root + await tabClick(page, 'tab2'); + await ionPageVisible(page, 'tab2childone'); + + await tabClick(page, 'tab2'); + await ionPageVisible(page, 'tab2'); + await ionPageDoesNotExist(page, 'tab2childone'); + await expect(page).toHaveURL(/\/tabs\/tab2(\?|$)/); + }); });