diff --git a/core/src/components/tabs/tabs.tsx b/core/src/components/tabs/tabs.tsx index e02e1aa91bd..ada833446ea 100644 --- a/core/src/components/tabs/tabs.tsx +++ b/core/src/components/tabs/tabs.tsx @@ -68,7 +68,27 @@ export class Tabs implements NavOutlet { componentWillRender() { const tabBar = this.el.querySelector('ion-tab-bar'); if (tabBar) { - const tab = this.selectedTab ? this.selectedTab.tab : undefined; + let tab = this.selectedTab ? this.selectedTab.tab : undefined; + + // Fallback: if no selectedTab is set but we're using router mode, + // determine the active tab from the current URL. This works around + // timing issues in React Router integration where setRouteId may not + // be called in time for the initial render. + // TODO(FW-6724): Remove this with React Router upgrade + if (!tab && this.useRouter && typeof window !== 'undefined') { + const currentPath = window.location.pathname; + const tabButtons = this.el.querySelectorAll('ion-tab-button'); + + // Look for a tab button that matches the current path pattern + for (const tabButton of tabButtons) { + const tabId = tabButton.getAttribute('tab'); + if (tabId && currentPath.includes(tabId)) { + tab = tabId; + break; + } + } + } + tabBar.selectedTab = tab; } } diff --git a/packages/react/test/base/src/App.tsx b/packages/react/test/base/src/App.tsx index 39ebb5f74ff..291acf7524f 100644 --- a/packages/react/test/base/src/App.tsx +++ b/packages/react/test/base/src/App.tsx @@ -27,6 +27,7 @@ import Main from './pages/Main'; import Tabs from './pages/Tabs'; import TabsBasic from './pages/TabsBasic'; import NavComponent from './pages/navigation/NavComponent'; +import TabsDirectNavigation from './pages/TabsDirectNavigation'; import IonModalConditional from './pages/overlay-components/IonModalConditional'; import IonModalConditionalSibling from './pages/overlay-components/IonModalConditionalSibling'; import IonModalDatetimeButton from './pages/overlay-components/IonModalDatetimeButton'; @@ -63,6 +64,7 @@ const App: React.FC = () => ( + diff --git a/packages/react/test/base/src/pages/TabsDirectNavigation.tsx b/packages/react/test/base/src/pages/TabsDirectNavigation.tsx new file mode 100644 index 00000000000..0e8df5db1f4 --- /dev/null +++ b/packages/react/test/base/src/pages/TabsDirectNavigation.tsx @@ -0,0 +1,94 @@ +import { IonContent, IonHeader, IonIcon, IonLabel, IonPage, IonRouterOutlet, IonTabBar, IonTabButton, IonTabs, IonTitle, IonToolbar } from '@ionic/react'; +import { homeOutline, radioOutline, libraryOutline, searchOutline } from 'ionicons/icons'; +import React from 'react'; +import { Route, Redirect } from 'react-router-dom'; + +const HomePage: React.FC = () => ( + + + + Home + + + +
Home Content
+
+
+); + +const RadioPage: React.FC = () => ( + + + + Radio + + + +
Radio Content
+
+
+); + +const LibraryPage: React.FC = () => ( + + + + Library + + + +
Library Content
+
+
+); + +const SearchPage: React.FC = () => ( + + + + Search + + + +
Search Content
+
+
+); + +const TabsDirectNavigation: React.FC = () => { + return ( + + + + } exact={true} /> + } exact={true} /> + } exact={true} /> + } exact={true} /> + + + + + + Home + + + + + Radio + + + + + Library + + + + + Search + + + + ); +}; + +export default TabsDirectNavigation; \ No newline at end of file diff --git a/packages/react/test/base/tests/e2e/specs/components/tabs-direct-navigation.cy.ts b/packages/react/test/base/tests/e2e/specs/components/tabs-direct-navigation.cy.ts new file mode 100644 index 00000000000..b1bc76cb5bc --- /dev/null +++ b/packages/react/test/base/tests/e2e/specs/components/tabs-direct-navigation.cy.ts @@ -0,0 +1,35 @@ +describe('Tabs Direct Navigation', () => { + it('should select the correct tab when navigating directly to home route', () => { + cy.visit('/tabs-direct-navigation/home'); + cy.get('[data-testid="home-tab"]').should('have.class', 'tab-selected'); + cy.get('[data-testid="home-content"]').should('be.visible'); + }); + + it('should select the correct tab when navigating directly to radio route', () => { + cy.visit('/tabs-direct-navigation/radio'); + cy.get('[data-testid="radio-tab"]').should('have.class', 'tab-selected'); + cy.get('[data-testid="radio-content"]').should('be.visible'); + }); + + it('should select the correct tab when navigating directly to library route', () => { + cy.visit('/tabs-direct-navigation/library'); + cy.get('[data-testid="library-tab"]').should('have.class', 'tab-selected'); + cy.get('[data-testid="library-content"]').should('be.visible'); + }); + + it('should select the correct tab when navigating directly to search route', () => { + cy.visit('/tabs-direct-navigation/search'); + cy.get('[data-testid="search-tab"]').should('have.class', 'tab-selected'); + cy.get('[data-testid="search-content"]').should('be.visible'); + }); + + it('should update tab selection when navigating between tabs', () => { + cy.visit('/tabs-direct-navigation/home'); + cy.get('[data-testid="home-tab"]').should('have.class', 'tab-selected'); + + cy.get('[data-testid="radio-tab"]').click(); + cy.get('[data-testid="radio-tab"]').should('have.class', 'tab-selected'); + cy.get('[data-testid="home-tab"]').should('not.have.class', 'tab-selected'); + cy.get('[data-testid="radio-content"]').should('be.visible'); + }); +}); \ No newline at end of file