diff --git a/packages/react/src/components/createInlineOverlayComponent.tsx b/packages/react/src/components/createInlineOverlayComponent.tsx index 26f6a9ac5e..5a1375385d 100644 --- a/packages/react/src/components/createInlineOverlayComponent.tsx +++ b/packages/react/src/components/createInlineOverlayComponent.tsx @@ -71,11 +71,11 @@ export const createInlineOverlayComponent = ( setupPageVisibilityObserver() { /** - * Watch for when ANY element in the document gets the ion-page-hidden class. + * Watch for when ancestor pages get the ion-page-hidden class. * We use a subtree observer on a parent container because: * 1. The overlay's component might not have an IonPage wrapper * 2. Pages might be added dynamically after this component mounts - * 3. We want to dismiss overlays when ANY navigation occurs + * 3. We want to dismiss overlays when navigation hides the containing page * * This handles React Router 6 where pages stay mounted but get hidden. */ @@ -87,8 +87,17 @@ export const createInlineOverlayComponent = ( const target = mutation.target as HTMLElement; // If any element gets the ion-page-hidden or ion-page-invisible class, dismiss overlay if (target.classList.contains('ion-page-hidden') || target.classList.contains('ion-page-invisible')) { - this.dismissOverlay(); - return; + /** + * Only dismiss the overlay if the hidden page is an ancestor of the overlay, + * not a descendant. Pages inside the overlay (e.g., IonPage in modal content) + * may get ion-page-invisible when they mount inside an outlet context, but + * this should not dismiss the overlay. + */ + const overlayElement = this.ref.current; + if (overlayElement && !overlayElement.contains(target)) { + this.dismissOverlay(); + return; + } } } } diff --git a/packages/react/test/apps/react17/package.json b/packages/react/test/apps/react17/package.json index 68079579bb..f05a10f55d 100644 --- a/packages/react/test/apps/react17/package.json +++ b/packages/react/test/apps/react17/package.json @@ -2,18 +2,22 @@ "name": "test-app", "version": "0.0.1", "private": true, + "overrides": { + "@ionic/react-router": { + "react-router": "$react-router", + "react-router-dom": "$react-router-dom" + } + }, "dependencies": { "@ionic/react": "^6.6.1", "@ionic/react-router": "^6.6.1", "@types/react": "^17.0.53", "@types/react-dom": "^17.0.19", - "@types/react-router": "^5.1.20", - "@types/react-router-dom": "^5.3.3", "ionicons": "^8.0.13", "react": "^17.0.2", "react-dom": "^17.0.2", - "react-router": "^5.3.4", - "react-router-dom": "^5.3.4", + "react-router": "^6.0.0", + "react-router-dom": "^6.0.0", "react-scripts": "^5.0.0", "typescript": "^4.1.3" }, diff --git a/packages/react/test/apps/react18/package.json b/packages/react/test/apps/react18/package.json index 65ab9e0023..38ce952149 100644 --- a/packages/react/test/apps/react18/package.json +++ b/packages/react/test/apps/react18/package.json @@ -2,14 +2,20 @@ "name": "test-app", "version": "0.0.1", "private": true, + "overrides": { + "@ionic/react-router": { + "react-router": "$react-router", + "react-router-dom": "$react-router-dom" + } + }, "dependencies": { "@ionic/react": "^7.0.0", "@ionic/react-router": "^7.0.0", "ionicons": "^8.0.13", "react": "^18.2.0", "react-dom": "^18.2.0", - "react-router": "^5.3.4", - "react-router-dom": "^5.3.4" + "react-router": "^6.0.0", + "react-router-dom": "^6.0.0" }, "scripts": { "dev": "vite", @@ -27,8 +33,6 @@ "@testing-library/user-event": "^14.4.3", "@types/react": "^18.0.27", "@types/react-dom": "^18.0.10", - "@types/react-router": "^5.1.20", - "@types/react-router-dom": "^5.3.3", "@vitejs/plugin-legacy": "^4.0.2", "@vitejs/plugin-react": "^4.0.1", "concurrently": "^6.3.0", diff --git a/packages/react/test/apps/react19/package.json b/packages/react/test/apps/react19/package.json index 67e3bf1db8..0a25b0d1aa 100644 --- a/packages/react/test/apps/react19/package.json +++ b/packages/react/test/apps/react19/package.json @@ -2,14 +2,20 @@ "name": "test-app", "version": "0.0.1", "private": true, + "overrides": { + "@ionic/react-router": { + "react-router": "$react-router", + "react-router-dom": "$react-router-dom" + } + }, "dependencies": { "@ionic/react": "^8.4.0", "@ionic/react-router": "^8.4.0", "ionicons": "^8.0.13", "react": "19.0.0", "react-dom": "19.0.0", - "react-router": "^5.3.4", - "react-router-dom": "^5.3.4" + "react-router": "^6.0.0", + "react-router-dom": "^6.0.0" }, "scripts": { "dev": "vite", @@ -27,8 +33,6 @@ "@testing-library/user-event": "^14.4.3", "@types/react": "19.0.10", "@types/react-dom": "19.0.4", - "@types/react-router": "^5.1.20", - "@types/react-router-dom": "^5.3.3", "@vitejs/plugin-legacy": "^4.0.2", "@vitejs/plugin-react": "^4.0.1", "concurrently": "^6.3.0", diff --git a/packages/react/test/base/scripts/sync.sh b/packages/react/test/base/scripts/sync.sh index a6b441d8b5..0626fbd8f0 100755 --- a/packages/react/test/base/scripts/sync.sh +++ b/packages/react/test/base/scripts/sync.sh @@ -15,4 +15,4 @@ npm pack ../../../ npm pack ../../../../react-router # Install Dependencies -npm install *.tgz --no-save +npm install *.tgz --no-save --legacy-peer-deps diff --git a/packages/react/test/base/src/App.tsx b/packages/react/test/base/src/App.tsx index 634af89f07..860c8c6931 100644 --- a/packages/react/test/base/src/App.tsx +++ b/packages/react/test/base/src/App.tsx @@ -1,7 +1,7 @@ import { IonApp, IonRouterOutlet, setupIonicReact } from '@ionic/react'; import { IonReactRouter } from '@ionic/react-router'; import React from 'react'; -import { Route } from 'react-router-dom'; +import { Route } from 'react-router'; /* Core CSS required for Ionic components to work properly */ import '@ionic/react/css/core.css'; @@ -45,32 +45,32 @@ const App: React.FC = () => ( - - - - + } /> + } /> + } /> + } /> } /> - + } /> } /> } /> - - - - - - - - - + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> diff --git a/packages/react/test/base/src/pages/Tabs.tsx b/packages/react/test/base/src/pages/Tabs.tsx index 2098bfcb26..89c82fd2c5 100644 --- a/packages/react/test/base/src/pages/Tabs.tsx +++ b/packages/react/test/base/src/pages/Tabs.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { IonLabel, IonRouterOutlet, IonTabBar, IonTabButton, IonTabs, IonPage } from '@ionic/react'; -import { Route, Redirect } from 'react-router'; +import { Route, Navigate } from 'react-router'; interface TabsProps {} @@ -9,8 +9,8 @@ const Tabs: React.FC = () => { - - Tab 1} /> + } /> + Tab 1} /> window.alert('Tab was clicked')}> diff --git a/packages/react/test/base/src/pages/TabsDirectNavigation.tsx b/packages/react/test/base/src/pages/TabsDirectNavigation.tsx index 2e412e174a..c02589ad6c 100644 --- a/packages/react/test/base/src/pages/TabsDirectNavigation.tsx +++ b/packages/react/test/base/src/pages/TabsDirectNavigation.tsx @@ -1,7 +1,7 @@ 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'; +import { Route, Navigate } from 'react-router'; const HomePage: React.FC = () => ( @@ -59,11 +59,11 @@ const TabsDirectNavigation: React.FC = () => { return ( - - } exact={true} /> - } exact={true} /> - } exact={true} /> - } exact={true} /> + } /> + } /> + } /> + } /> + } /> diff --git a/packages/react/test/base/src/pages/overlay-components/OverlayComponents.tsx b/packages/react/test/base/src/pages/overlay-components/OverlayComponents.tsx index 19aebc9081..29b4363a7a 100644 --- a/packages/react/test/base/src/pages/overlay-components/OverlayComponents.tsx +++ b/packages/react/test/base/src/pages/overlay-components/OverlayComponents.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { IonIcon, IonLabel, IonRouterOutlet, IonTabBar, IonTabButton, IonTabs } from '@ionic/react'; -import { Route, Redirect } from 'react-router'; +import { Route, Navigate } from 'react-router'; import { addCircleOutline, alarm, @@ -26,16 +26,16 @@ const OverlayHooks: React.FC = () => { return ( - - - - - - - - - - + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> diff --git a/packages/react/test/base/src/pages/overlay-hooks/OverlayHooks.tsx b/packages/react/test/base/src/pages/overlay-hooks/OverlayHooks.tsx index 4cc9bf88dd..8036c0efbe 100644 --- a/packages/react/test/base/src/pages/overlay-hooks/OverlayHooks.tsx +++ b/packages/react/test/base/src/pages/overlay-hooks/OverlayHooks.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { IonIcon, IonLabel, IonRouterOutlet, IonTabBar, IonTabButton, IonTabs } from '@ionic/react'; -import { Route, Redirect } from 'react-router'; +import { Route, Navigate } from 'react-router'; import ActionSheetHook from './ActionSheetHook'; import { addCircleOutline, @@ -24,14 +24,14 @@ const OverlayHooks: React.FC = () => { return ( - - - - - - - - + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } />