mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-11-08 15:51:16 +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 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() {
|
||||
|
||||
@ -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('<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 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());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -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('<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 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 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 { 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.
|
||||
*/
|
||||
|
||||
@ -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('<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 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 { 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.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user