diff --git a/core/src/components/modal/test/dismiss-behavior/index.html b/core/src/components/modal/test/dismiss-behavior/index.html
new file mode 100644
index 00000000000..448b84457d9
--- /dev/null
+++ b/core/src/components/modal/test/dismiss-behavior/index.html
@@ -0,0 +1,97 @@
+
+
+
+
+ Modal - Dismiss Behavior
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Modal - Dismiss Behavior
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/core/src/components/modal/test/dismiss-behavior/modal.e2e.ts b/core/src/components/modal/test/dismiss-behavior/modal.e2e.ts
new file mode 100644
index 00000000000..7969317c447
--- /dev/null
+++ b/core/src/components/modal/test/dismiss-behavior/modal.e2e.ts
@@ -0,0 +1,58 @@
+import { expect } from '@playwright/test';
+import { configs, test } from '@utils/test/playwright';
+
+configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
+ test.describe(title('modal: dismiss behavior'), () => {
+ test.describe(title('modal: default dismiss'), () => {
+ test('should dismiss the last presented modal when the default dismiss button is clicked', async ({ page }) => {
+ await page.goto('/src/components/modal/test/dismiss-behavior', config);
+
+ const ionModalDidPresent = await page.spyOnEvent('ionModalDidPresent');
+ const ionModalDidDismiss = await page.spyOnEvent('ionModalDidDismiss');
+
+ await page.click('#present-first-modal');
+ await ionModalDidPresent.next();
+ const firstModal = page.locator('ion-modal[data-testid="modal-1"]');
+ await expect(firstModal).toBeVisible();
+
+ await page.click('#present-next-modal');
+ await ionModalDidPresent.next();
+ const secondModal = page.locator('ion-modal[data-testid="modal-2"]');
+ await expect(secondModal).toBeVisible();
+
+ await page.click('ion-modal[data-testid="modal-2"] ion-button.dismiss-default');
+ await ionModalDidDismiss.next();
+ await secondModal.waitFor({ state: 'detached' });
+
+ await expect(firstModal).toBeVisible();
+ await expect(secondModal).toBeHidden();
+ });
+ });
+
+ test.describe(title('modal: dismiss by id'), () => {
+ test('should dismiss the last presented modal when the dismiss by id button is clicked', async ({ page }) => {
+ await page.goto('/src/components/modal/test/dismiss-behavior', config);
+
+ const ionModalDidPresent = await page.spyOnEvent('ionModalDidPresent');
+ const ionModalDidDismiss = await page.spyOnEvent('ionModalDidDismiss');
+
+ await page.click('#present-first-modal');
+ await ionModalDidPresent.next();
+ const firstModal = page.locator('ion-modal[data-testid="modal-1"]');
+ await expect(firstModal).toBeVisible();
+
+ await page.click('#present-next-modal');
+ await ionModalDidPresent.next();
+ const secondModal = page.locator('ion-modal[data-testid="modal-2"]');
+ await expect(secondModal).toBeVisible();
+
+ await page.click('ion-modal[data-testid="modal-2"] ion-button.dismiss-by-id');
+ await ionModalDidDismiss.next();
+ await secondModal.waitFor({ state: 'detached' });
+
+ await expect(firstModal).toBeVisible();
+ await expect(secondModal).toBeHidden();
+ });
+ });
+ });
+});
diff --git a/core/src/components/modal/test/modal-id.spec.tsx b/core/src/components/modal/test/modal-id.spec.tsx
index 43f1a9eaa16..93b6d34fa91 100644
--- a/core/src/components/modal/test/modal-id.spec.tsx
+++ b/core/src/components/modal/test/modal-id.spec.tsx
@@ -1,7 +1,7 @@
+import { h } from '@stencil/core';
import { newSpecPage } from '@stencil/core/testing';
import { Modal } from '../modal';
-import { h } from '@stencil/core';
describe('modal: id', () => {
it('modal should be assigned an incrementing id', async () => {
@@ -52,4 +52,21 @@ describe('modal: id', () => {
const alert = page.body.querySelector('ion-modal')!;
expect(alert.id).toBe(id);
});
+
+ it('should allow multiple modals with the same id', async () => {
+ const sharedId = 'shared-modal-id';
+
+ const page = await newSpecPage({
+ components: [Modal],
+ template: () => [
+ ,
+ ,
+ ],
+ });
+
+ const modals = page.body.querySelectorAll('ion-modal');
+ expect(modals.length).toBe(2);
+ expect(modals[0].id).toBe(sharedId);
+ expect(modals[1].id).toBe(sharedId);
+ });
});
diff --git a/core/src/utils/overlays.ts b/core/src/utils/overlays.ts
index 472a57559d3..59b341a7d52 100644
--- a/core/src/utils/overlays.ts
+++ b/core/src/utils/overlays.ts
@@ -473,7 +473,9 @@ export const getPresentedOverlay = (
id?: string
): HTMLIonOverlayElement | undefined => {
const overlays = getPresentedOverlays(doc, overlayTag);
- return id === undefined ? overlays[overlays.length - 1] : overlays.find((o) => o.id === id);
+ // If no id is provided, return the last presented overlay
+ // Otherwise, return the last overlay with the given id
+ return (id === undefined ? overlays : overlays.filter((o: HTMLIonOverlayElement) => o.id === id)).slice(-1)[0];
};
/**