diff --git a/core/src/components/datetime-button/test/basic/datetime-button.e2e.ts b/core/src/components/datetime-button/test/basic/datetime-button.e2e.ts
index c236fc8d2b0..cca426a6fab 100644
--- a/core/src/components/datetime-button/test/basic/datetime-button.e2e.ts
+++ b/core/src/components/datetime-button/test/basic/datetime-button.e2e.ts
@@ -17,6 +17,7 @@ test.describe('datetime-button: switching to correct view', () => {
expect(datetime).toHaveJSProperty('presentation', 'date-time');
await page.locator('#date-button').click();
+ await page.waitForChanges();
expect(datetime).toHaveJSProperty('presentation', 'date');
});
@@ -25,6 +26,7 @@ test.describe('datetime-button: switching to correct view', () => {
expect(datetime).toHaveJSProperty('presentation', 'date-time');
await page.locator('#time-button').click();
+ await page.waitForChanges();
expect(datetime).toHaveJSProperty('presentation', 'time');
});
diff --git a/core/src/components/modal/test/inline/modal.e2e.ts b/core/src/components/modal/test/inline/modal.e2e.ts
index c215da0a4be..75f0546f0f9 100644
--- a/core/src/components/modal/test/inline/modal.e2e.ts
+++ b/core/src/components/modal/test/inline/modal.e2e.ts
@@ -21,4 +21,44 @@ test.describe('modal: inline', () => {
expect(await page.screenshot()).toMatchSnapshot(`modal-inline-dismiss-${page.getSnapshotSettings()}.png`);
});
+
+ test('presenting should create a single root element with the ion-page class', async ({ page, skip }, testInfo) => {
+ skip.mode('md');
+ skip.rtl();
+
+ testInfo.annotations.push({
+ type: 'issue',
+ description: 'https://github.com/ionic-team/ionic-framework/issues/26117',
+ });
+
+ await page.setContent(`
+
+
+
+
+
+ `);
+
+ const ionModalDidPresent = await page.spyOnEvent('ionModalDidPresent');
+ const ionModalDidDismiss = await page.spyOnEvent('ionModalDidDismiss');
+ const modal = page.locator('ion-modal');
+
+ await page.locator('#date-button').click();
+ await ionModalDidPresent.next();
+
+ // Verifies that the host element exists with the .ion-page class
+ expect(await modal.evaluate((el: HTMLIonModalElement) => el.firstElementChild!.className)).toContain('ion-page');
+
+ await modal.evaluate((el: HTMLIonModalElement) => el.dismiss());
+ await ionModalDidDismiss.next();
+
+ await page.locator('#date-button').click();
+ await ionModalDidPresent.next();
+
+ // Verifies that presenting the overlay again does not create a new host element
+ expect(await modal.evaluate((el: HTMLIonModalElement) => el.firstElementChild!.className)).toContain('ion-page');
+ expect(
+ await modal.evaluate((el: HTMLIonModalElement) => el.firstElementChild!.firstElementChild!.className)
+ ).not.toContain('ion-page');
+ });
});
diff --git a/core/src/utils/framework-delegate.ts b/core/src/utils/framework-delegate.ts
index d3b6ff382c7..af4f24a2be7 100644
--- a/core/src/utils/framework-delegate.ts
+++ b/core/src/utils/framework-delegate.ts
@@ -87,14 +87,22 @@ export const CoreDelegate = () => {
await new Promise((resolve) => componentOnReady(el, resolve));
} else if (BaseComponent.children.length > 0) {
- // If there is no component, then we need to create a new parent
- // element to apply the css classes to.
- const el = BaseComponent.ownerDocument?.createElement('div');
- cssClasses.forEach((c) => el.classList.add(c));
- // Move each child from the original template to the new parent element.
- el.append(...BaseComponent.children);
- // Append the new parent element to the original parent element.
- BaseComponent.appendChild(el);
+ const root = BaseComponent.children[0] as HTMLElement;
+ if (!root.classList.contains('ion-delegate-host')) {
+ /**
+ * If the root element is not a delegate host, it means
+ * that the overlay has not been presented yet and we need
+ * to create the containing element with the specified classes.
+ */
+ const el = BaseComponent.ownerDocument?.createElement('div');
+ // Add a class to track if the root element was created by the delegate.
+ el.classList.add('ion-delegate-host');
+ cssClasses.forEach((c) => el.classList.add(c));
+ // Move each child from the original template to the new parent element.
+ el.append(...BaseComponent.children);
+ // Append the new parent element to the original parent element.
+ BaseComponent.appendChild(el);
+ }
}
/**