diff --git a/core/src/components/action-sheet/action-sheet.tsx b/core/src/components/action-sheet/action-sheet.tsx
index 9a877054cf..0c94a9410f 100644
--- a/core/src/components/action-sheet/action-sheet.tsx
+++ b/core/src/components/action-sheet/action-sheet.tsx
@@ -2,6 +2,7 @@ import type { ComponentInterface, EventEmitter } from '@stencil/core';
import { Watch, Component, Element, Event, Host, Method, Prop, h, readTask } from '@stencil/core';
import type { Gesture } from '@utils/gesture';
import { createButtonActiveGesture } from '@utils/gesture/button-active';
+import { raf } from '@utils/helpers';
import {
BACKDROP,
createDelegateController,
@@ -318,25 +319,32 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
componentDidLoad() {
/**
- * Do not create gesture if:
- * 1. A gesture already exists
- * 2. App is running in MD mode
- * 3. A wrapper ref does not exist
+ * Only create gesture if:
+ * 1. A gesture does not already exist
+ * 2. App is running in iOS mode
+ * 3. A wrapper ref exists
+ * 4. A group ref exists
*/
const { groupEl, wrapperEl } = this;
- if (this.gesture || getIonMode(this) === 'md' || !wrapperEl || !groupEl) {
- return;
+ if (!this.gesture && getIonMode(this) === 'ios' && wrapperEl && groupEl) {
+ readTask(() => {
+ const isScrollable = groupEl.scrollHeight > groupEl.clientHeight;
+ if (!isScrollable) {
+ this.gesture = createButtonActiveGesture(wrapperEl, (refEl: HTMLElement) =>
+ refEl.classList.contains('action-sheet-button')
+ );
+ this.gesture.enable(true);
+ }
+ });
}
- readTask(() => {
- const isScrollable = groupEl.scrollHeight > groupEl.clientHeight;
- if (!isScrollable) {
- this.gesture = createButtonActiveGesture(wrapperEl, (refEl: HTMLElement) =>
- refEl.classList.contains('action-sheet-button')
- );
- this.gesture.enable(true);
- }
- });
+ /**
+ * If action sheet was rendered with isOpen="true"
+ * then we should open action sheet immediately.
+ */
+ if (this.isOpen === true) {
+ raf(() => this.present());
+ }
}
render() {
diff --git a/core/src/components/action-sheet/test/is-open/action-sheet.e2e.ts b/core/src/components/action-sheet/test/is-open/action-sheet.e2e.ts
index 66eca8e6f0..512921485e 100644
--- a/core/src/components/action-sheet/test/is-open/action-sheet.e2e.ts
+++ b/core/src/components/action-sheet/test/is-open/action-sheet.e2e.ts
@@ -30,5 +30,10 @@ configs({ directions: ['ltr'], modes: ['ios'] }).forEach(({ config, title }) =>
await expect(actionSheet).toBeHidden();
});
+
+ test('should open if isOpen is true on load', async ({ page }) => {
+ await page.setContent('', config);
+ await expect(page.locator('ion-action-sheet')).toBeVisible();
+ });
});
});
diff --git a/core/src/components/alert/alert.tsx b/core/src/components/alert/alert.tsx
index 8ce5094492..0c67665bf9 100644
--- a/core/src/components/alert/alert.tsx
+++ b/core/src/components/alert/alert.tsx
@@ -3,6 +3,7 @@ import { Component, Element, Event, Host, Listen, Method, Prop, Watch, forceUpda
import { ENABLE_HTML_CONTENT_DEFAULT } from '@utils/config';
import type { Gesture } from '@utils/gesture';
import { createButtonActiveGesture } from '@utils/gesture/button-active';
+import { raf } from '@utils/helpers';
import {
createDelegateController,
createTriggerController,
@@ -346,19 +347,25 @@ export class Alert implements ComponentInterface, OverlayInterface {
componentDidLoad() {
/**
- * Do not create gesture if:
- * 1. A gesture already exists
- * 2. App is running in MD mode
- * 3. A wrapper ref does not exist
+ * Only create gesture if:
+ * 1. A gesture does not already exist
+ * 2. App is running in iOS mode
+ * 3. A wrapper ref exists
*/
- if (this.gesture || getIonMode(this) === 'md' || !this.wrapperEl) {
- return;
+ if (!this.gesture && getIonMode(this) === 'ios' && this.wrapperEl) {
+ this.gesture = createButtonActiveGesture(this.wrapperEl, (refEl: HTMLElement) =>
+ refEl.classList.contains('alert-button')
+ );
+ this.gesture.enable(true);
}
- this.gesture = createButtonActiveGesture(this.wrapperEl, (refEl: HTMLElement) =>
- refEl.classList.contains('alert-button')
- );
- this.gesture.enable(true);
+ /**
+ * If alert was rendered with isOpen="true"
+ * then we should open alert immediately.
+ */
+ if (this.isOpen === true) {
+ raf(() => this.present());
+ }
}
/**
diff --git a/core/src/components/alert/test/is-open/alert.e2e.ts b/core/src/components/alert/test/is-open/alert.e2e.ts
index 5fa7980c7e..84fadf6997 100644
--- a/core/src/components/alert/test/is-open/alert.e2e.ts
+++ b/core/src/components/alert/test/is-open/alert.e2e.ts
@@ -29,5 +29,10 @@ configs({ directions: ['ltr'], modes: ['ios'] }).forEach(({ config, title }) =>
await ionAlertDidDismiss.next();
await expect(alert).toBeHidden();
});
+
+ test('should open if isOpen is true on load', async ({ page }) => {
+ await page.setContent('', config);
+ await expect(page.locator('ion-alert')).toBeVisible();
+ });
});
});
diff --git a/core/src/components/loading/test/is-open/loading.e2e.ts b/core/src/components/loading/test/is-open/loading.e2e.ts
index 9a3020b2d0..06bfdcacb9 100644
--- a/core/src/components/loading/test/is-open/loading.e2e.ts
+++ b/core/src/components/loading/test/is-open/loading.e2e.ts
@@ -23,5 +23,10 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
await ionLoadingDidDismiss.next();
await expect(loading).toBeHidden();
});
+
+ test('should open if isOpen is true on load', async ({ page }) => {
+ await page.setContent('', config);
+ await expect(page.locator('ion-loading')).toBeVisible();
+ });
});
});
diff --git a/core/src/components/modal/test/is-open/modal.e2e.ts b/core/src/components/modal/test/is-open/modal.e2e.ts
index b56e0333d2..651505f43f 100644
--- a/core/src/components/modal/test/is-open/modal.e2e.ts
+++ b/core/src/components/modal/test/is-open/modal.e2e.ts
@@ -20,5 +20,10 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
await ionModalDidDismiss.next();
await expect(modal).toBeHidden();
});
+
+ test('should open if isOpen is true on load', async ({ page }) => {
+ await page.setContent('', config);
+ await expect(page.locator('ion-modal')).toBeVisible();
+ });
});
});
diff --git a/core/src/components/picker/picker.tsx b/core/src/components/picker/picker.tsx
index 66eeb0aa0c..9f1f587086 100644
--- a/core/src/components/picker/picker.tsx
+++ b/core/src/components/picker/picker.tsx
@@ -1,5 +1,6 @@
import type { ComponentInterface, EventEmitter } from '@stencil/core';
import { Component, Element, Event, Host, Method, Prop, State, Watch, h } from '@stencil/core';
+import { raf } from '@utils/helpers';
import {
createDelegateController,
createTriggerController,
@@ -199,6 +200,16 @@ export class Picker implements ComponentInterface, OverlayInterface {
setOverlayId(this.el);
}
+ componentDidLoad() {
+ /**
+ * If picker was rendered with isOpen="true"
+ * then we should open picker immediately.
+ */
+ if (this.isOpen === true) {
+ raf(() => this.present());
+ }
+ }
+
/**
* Present the picker overlay after it has been created.
*/
diff --git a/core/src/components/picker/test/is-open/picker.e2e.ts b/core/src/components/picker/test/is-open/picker.e2e.ts
index ab977cdb43..026da1abfd 100644
--- a/core/src/components/picker/test/is-open/picker.e2e.ts
+++ b/core/src/components/picker/test/is-open/picker.e2e.ts
@@ -23,5 +23,10 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
await ionPickerDidDismiss.next();
await expect(picker).toBeHidden();
});
+
+ test('should open if isOpen is true on load', async ({ page }) => {
+ await page.setContent('', config);
+ await expect(page.locator('ion-picker')).toBeVisible();
+ });
});
});
diff --git a/core/src/components/popover/test/is-open/popover.e2e.ts b/core/src/components/popover/test/is-open/popover.e2e.ts
new file mode 100644
index 0000000000..cd3604a2fb
--- /dev/null
+++ b/core/src/components/popover/test/is-open/popover.e2e.ts
@@ -0,0 +1,11 @@
+import { expect } from '@playwright/test';
+import { configs, test } from '@utils/test/playwright';
+
+configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
+ test.describe(title('popover: isOpen'), () => {
+ test('should open if isOpen is true on load', async ({ page }) => {
+ await page.setContent('', config);
+ await expect(page.locator('ion-popover')).toBeVisible();
+ });
+ });
+});
diff --git a/core/src/components/toast/test/is-open/toast.e2e.ts b/core/src/components/toast/test/is-open/toast.e2e.ts
index 2cb6daa4bf..8d55e1b192 100644
--- a/core/src/components/toast/test/is-open/toast.e2e.ts
+++ b/core/src/components/toast/test/is-open/toast.e2e.ts
@@ -24,5 +24,10 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
await ionToastDidDismiss.next();
await expect(toast).toBeHidden();
});
+
+ test('should open if isOpen is true on load', async ({ page }) => {
+ await page.setContent('', config);
+ await expect(page.locator('ion-toast')).toBeVisible();
+ });
});
});
diff --git a/core/src/components/toast/toast.tsx b/core/src/components/toast/toast.tsx
index 4f397d94a7..f0efc640ad 100644
--- a/core/src/components/toast/toast.tsx
+++ b/core/src/components/toast/toast.tsx
@@ -1,6 +1,7 @@
import type { ComponentInterface, EventEmitter } from '@stencil/core';
import { State, Watch, Component, Element, Event, h, Host, Method, Prop } from '@stencil/core';
import { ENABLE_HTML_CONTENT_DEFAULT } from '@utils/config';
+import { raf } from '@utils/helpers';
import { printIonWarning } from '@utils/logging';
import {
createDelegateController,
@@ -253,6 +254,16 @@ export class Toast implements ComponentInterface, OverlayInterface {
setOverlayId(this.el);
}
+ componentDidLoad() {
+ /**
+ * If toast was rendered with isOpen="true"
+ * then we should open toast immediately.
+ */
+ if (this.isOpen === true) {
+ raf(() => this.present());
+ }
+ }
+
/**
* Present the toast overlay after it has been created.
*/