mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-11-08 23:58:13 +08:00
fix(many): overlays present if isOpen is true on load (#27933)
Issue number: resolves #27928 --------- <!-- Please do not submit updates to dependencies unless it fixes an issue. --> <!-- Please try to limit your pull request to one type (bugfix, feature, etc). Submit multiple pull requests if needed. --> ## What is the current behavior? <!-- Please describe the current behavior that you are modifying. --> Action sheet, alert, picker, and toast did not have logic where the overlay presents if `isOpen="true"` on load. Modal, popover, and loading had this logic but did not have test coverage. ## What is the new behavior? <!-- Please describe the behavior or changes that are being added by this PR. --> - Updated action sheet, alert, picker, and toast to present if `isOpen="true"` on load - Added test coverage to all overlays for this functionality. ## Does this introduce a breaking change? - [ ] Yes - [x] No <!-- If this introduces a breaking change, please describe the impact and migration path for existing applications below. --> ## Other information <!-- Any other information that is important to this PR such as screenshots of how the component looks before and after the change. --> Dev build: `7.2.3-dev.11691156718.1638345c`
This commit is contained in:
@ -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 { Watch, Component, Element, Event, Host, Method, Prop, h, readTask } from '@stencil/core';
|
||||||
import type { Gesture } from '@utils/gesture';
|
import type { Gesture } from '@utils/gesture';
|
||||||
import { createButtonActiveGesture } from '@utils/gesture/button-active';
|
import { createButtonActiveGesture } from '@utils/gesture/button-active';
|
||||||
|
import { raf } from '@utils/helpers';
|
||||||
import {
|
import {
|
||||||
BACKDROP,
|
BACKDROP,
|
||||||
createDelegateController,
|
createDelegateController,
|
||||||
@ -318,25 +319,32 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
|
|||||||
|
|
||||||
componentDidLoad() {
|
componentDidLoad() {
|
||||||
/**
|
/**
|
||||||
* Do not create gesture if:
|
* Only create gesture if:
|
||||||
* 1. A gesture already exists
|
* 1. A gesture does not already exist
|
||||||
* 2. App is running in MD mode
|
* 2. App is running in iOS mode
|
||||||
* 3. A wrapper ref does not exist
|
* 3. A wrapper ref exists
|
||||||
|
* 4. A group ref exists
|
||||||
*/
|
*/
|
||||||
const { groupEl, wrapperEl } = this;
|
const { groupEl, wrapperEl } = this;
|
||||||
if (this.gesture || getIonMode(this) === 'md' || !wrapperEl || !groupEl) {
|
if (!this.gesture && getIonMode(this) === 'ios' && wrapperEl && groupEl) {
|
||||||
return;
|
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 action sheet was rendered with isOpen="true"
|
||||||
if (!isScrollable) {
|
* then we should open action sheet immediately.
|
||||||
this.gesture = createButtonActiveGesture(wrapperEl, (refEl: HTMLElement) =>
|
*/
|
||||||
refEl.classList.contains('action-sheet-button')
|
if (this.isOpen === true) {
|
||||||
);
|
raf(() => this.present());
|
||||||
this.gesture.enable(true);
|
}
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|||||||
@ -30,5 +30,10 @@ configs({ directions: ['ltr'], modes: ['ios'] }).forEach(({ config, title }) =>
|
|||||||
|
|
||||||
await expect(actionSheet).toBeHidden();
|
await expect(actionSheet).toBeHidden();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should open if isOpen is true on load', async ({ page }) => {
|
||||||
|
await page.setContent('<ion-action-sheet is-open="true"></ion-action-sheet>', config);
|
||||||
|
await expect(page.locator('ion-action-sheet')).toBeVisible();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import { Component, Element, Event, Host, Listen, Method, Prop, Watch, forceUpda
|
|||||||
import { ENABLE_HTML_CONTENT_DEFAULT } from '@utils/config';
|
import { ENABLE_HTML_CONTENT_DEFAULT } from '@utils/config';
|
||||||
import type { Gesture } from '@utils/gesture';
|
import type { Gesture } from '@utils/gesture';
|
||||||
import { createButtonActiveGesture } from '@utils/gesture/button-active';
|
import { createButtonActiveGesture } from '@utils/gesture/button-active';
|
||||||
|
import { raf } from '@utils/helpers';
|
||||||
import {
|
import {
|
||||||
createDelegateController,
|
createDelegateController,
|
||||||
createTriggerController,
|
createTriggerController,
|
||||||
@ -346,19 +347,25 @@ export class Alert implements ComponentInterface, OverlayInterface {
|
|||||||
|
|
||||||
componentDidLoad() {
|
componentDidLoad() {
|
||||||
/**
|
/**
|
||||||
* Do not create gesture if:
|
* Only create gesture if:
|
||||||
* 1. A gesture already exists
|
* 1. A gesture does not already exist
|
||||||
* 2. App is running in MD mode
|
* 2. App is running in iOS mode
|
||||||
* 3. A wrapper ref does not exist
|
* 3. A wrapper ref exists
|
||||||
*/
|
*/
|
||||||
if (this.gesture || getIonMode(this) === 'md' || !this.wrapperEl) {
|
if (!this.gesture && getIonMode(this) === 'ios' && this.wrapperEl) {
|
||||||
return;
|
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')
|
* If alert was rendered with isOpen="true"
|
||||||
);
|
* then we should open alert immediately.
|
||||||
this.gesture.enable(true);
|
*/
|
||||||
|
if (this.isOpen === true) {
|
||||||
|
raf(() => this.present());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -29,5 +29,10 @@ configs({ directions: ['ltr'], modes: ['ios'] }).forEach(({ config, title }) =>
|
|||||||
await ionAlertDidDismiss.next();
|
await ionAlertDidDismiss.next();
|
||||||
await expect(alert).toBeHidden();
|
await expect(alert).toBeHidden();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should open if isOpen is true on load', async ({ page }) => {
|
||||||
|
await page.setContent('<ion-alert is-open="true"></ion-alert>', config);
|
||||||
|
await expect(page.locator('ion-alert')).toBeVisible();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -23,5 +23,10 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
|||||||
await ionLoadingDidDismiss.next();
|
await ionLoadingDidDismiss.next();
|
||||||
await expect(loading).toBeHidden();
|
await expect(loading).toBeHidden();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should open if isOpen is true on load', async ({ page }) => {
|
||||||
|
await page.setContent('<ion-loading is-open="true"></ion-loading>', config);
|
||||||
|
await expect(page.locator('ion-loading')).toBeVisible();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -20,5 +20,10 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
|||||||
await ionModalDidDismiss.next();
|
await ionModalDidDismiss.next();
|
||||||
await expect(modal).toBeHidden();
|
await expect(modal).toBeHidden();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should open if isOpen is true on load', async ({ page }) => {
|
||||||
|
await page.setContent('<ion-modal is-open="true"></ion-modal>', config);
|
||||||
|
await expect(page.locator('ion-modal')).toBeVisible();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import type { ComponentInterface, EventEmitter } from '@stencil/core';
|
import type { ComponentInterface, EventEmitter } from '@stencil/core';
|
||||||
import { Component, Element, Event, Host, Method, Prop, State, Watch, h } from '@stencil/core';
|
import { Component, Element, Event, Host, Method, Prop, State, Watch, h } from '@stencil/core';
|
||||||
|
import { raf } from '@utils/helpers';
|
||||||
import {
|
import {
|
||||||
createDelegateController,
|
createDelegateController,
|
||||||
createTriggerController,
|
createTriggerController,
|
||||||
@ -199,6 +200,16 @@ export class Picker implements ComponentInterface, OverlayInterface {
|
|||||||
setOverlayId(this.el);
|
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.
|
* Present the picker overlay after it has been created.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -23,5 +23,10 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
|||||||
await ionPickerDidDismiss.next();
|
await ionPickerDidDismiss.next();
|
||||||
await expect(picker).toBeHidden();
|
await expect(picker).toBeHidden();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should open if isOpen is true on load', async ({ page }) => {
|
||||||
|
await page.setContent('<ion-picker is-open="true"></ion-picker>', config);
|
||||||
|
await expect(page.locator('ion-picker')).toBeVisible();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
11
core/src/components/popover/test/is-open/popover.e2e.ts
Normal file
11
core/src/components/popover/test/is-open/popover.e2e.ts
Normal file
@ -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('<ion-popover is-open="true"></ion-popover>', config);
|
||||||
|
await expect(page.locator('ion-popover')).toBeVisible();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -24,5 +24,10 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
|||||||
await ionToastDidDismiss.next();
|
await ionToastDidDismiss.next();
|
||||||
await expect(toast).toBeHidden();
|
await expect(toast).toBeHidden();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should open if isOpen is true on load', async ({ page }) => {
|
||||||
|
await page.setContent('<ion-toast is-open="true"></ion-toast>', config);
|
||||||
|
await expect(page.locator('ion-toast')).toBeVisible();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import type { ComponentInterface, EventEmitter } from '@stencil/core';
|
import type { ComponentInterface, EventEmitter } from '@stencil/core';
|
||||||
import { State, Watch, Component, Element, Event, h, Host, Method, Prop } 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 { ENABLE_HTML_CONTENT_DEFAULT } from '@utils/config';
|
||||||
|
import { raf } from '@utils/helpers';
|
||||||
import { printIonWarning } from '@utils/logging';
|
import { printIonWarning } from '@utils/logging';
|
||||||
import {
|
import {
|
||||||
createDelegateController,
|
createDelegateController,
|
||||||
@ -253,6 +254,16 @@ export class Toast implements ComponentInterface, OverlayInterface {
|
|||||||
setOverlayId(this.el);
|
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.
|
* Present the toast overlay after it has been created.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user