diff --git a/core/src/components/modal/gestures/swipe-to-close.ts b/core/src/components/modal/gestures/swipe-to-close.ts index 9acc5d5169..7ce0d255b1 100644 --- a/core/src/components/modal/gestures/swipe-to-close.ts +++ b/core/src/components/modal/gestures/swipe-to-close.ts @@ -1,5 +1,6 @@ import type { Animation } from '../../../interface'; import { getTimeGivenProgression } from '../../../utils/animation/cubic-bezier'; +import { isIonContent } from '../../../utils/content'; import type { GestureDetail } from '../../../utils/gesture'; import { createGesture } from '../../../utils/gesture'; import { clamp } from '../../../utils/helpers'; @@ -11,11 +12,46 @@ export const SwipeToCloseDefaults = { MIN_PRESENTING_SCALE: 0.93, }; -export const createSwipeToCloseGesture = (el: HTMLIonModalElement, animation: Animation, onDismiss: () => void) => { +export const createSwipeToCloseGesture = ( + el: HTMLIonModalElement, + contentEl: HTMLElement, + scrollEl: HTMLElement, + animation: Animation, + onDismiss: () => void +) => { const height = el.offsetHeight; let isOpen = false; let canDismissBlocksGesture = false; const canDismissMaxStep = 0.2; + const getScrollY = () => { + if (isIonContent(contentEl)) { + return (contentEl as HTMLIonContentElement).scrollY; + /** + * Custom scroll containers are intended to be + * used with virtual scrolling, so we assume + * there is scrolling in this case. + */ + } else { + return true; + } + }; + const initialScrollY = getScrollY(); + + const disableContentScroll = () => { + if (isIonContent(contentEl)) { + (contentEl as HTMLIonContentElement).scrollY = false; + } else { + contentEl.style.setProperty('overflow', 'hidden'); + } + }; + + const resetContentScroll = () => { + if (isIonContent(contentEl)) { + (contentEl as HTMLIonContentElement).scrollY = initialScrollY; + } else { + contentEl.style.removeProperty('overflow'); + } + }; const canStart = (detail: GestureDetail) => { const target = detail.event.target as HTMLElement | null; @@ -24,17 +60,32 @@ export const createSwipeToCloseGesture = (el: HTMLIonModalElement, animation: An return true; } - const contentOrFooter = target.closest('ion-content, ion-footer'); - if (contentOrFooter === null) { + /** + * If we are swiping on the content, + * swiping should only be possible if + * the content is scrolled all the way + * to the top so that we do not interfere + * with scrolling. + */ + const content = target.closest('ion-content'); + if (content) { + return scrollEl.scrollTop === 0; + } + + /** + * Card should be swipeable on all + * parts of the modal except for the footer. + */ + const footer = target.closest('ion-footer'); + if (footer === null) { return true; } - // Target is in the content or the footer so do not start the gesture. - // We could be more nuanced here and allow it for content that - // does not need to scroll. + return false; }; - const onStart = () => { + const onStart = (detail: GestureDetail) => { + const { deltaY } = detail; /** * If canDismiss is anything other than `true` * then users should be able to swipe down @@ -43,11 +94,46 @@ export const createSwipeToCloseGesture = (el: HTMLIonModalElement, animation: An * TODO (FW-937) * Remove undefined check */ + canDismissBlocksGesture = el.canDismiss !== undefined && el.canDismiss !== true; + + /** + * If we are pulling down, then + * it is possible we are pulling on the + * content. We do not want scrolling to + * happen at the same time as the gesture. + */ + if (deltaY > 0) { + disableContentScroll(); + } + animation.progressStart(true, isOpen ? 1 : 0); }; const onMove = (detail: GestureDetail) => { + const { deltaY } = detail; + + /** + * If we are pulling down, then + * it is possible we are pulling on the + * content. We do not want scrolling to + * happen at the same time as the gesture. + */ + if (deltaY > 0) { + disableContentScroll(); + } + + /** + * If we are swiping on the content + * then the swipe gesture should only + * happen if we are pulling down. + * + * However, if we pull up and + * then down such that the scroll position + * returns to 0, we should be able to swipe + * the card. + */ + const step = detail.deltaY / height; /** @@ -117,6 +203,8 @@ export const createSwipeToCloseGesture = (el: HTMLIonModalElement, animation: An gesture.enable(false); + resetContentScroll(); + animation .onFinish(() => { if (!shouldComplete) { diff --git a/core/src/components/modal/modal.tsx b/core/src/components/modal/modal.tsx index 840d33c73e..1c66ac9713 100644 --- a/core/src/components/modal/modal.tsx +++ b/core/src/components/modal/modal.tsx @@ -15,6 +15,7 @@ import type { OverlayEventDetail, OverlayInterface, } from '../../interface'; +import { getScrollElement, findIonContent, printIonContentErrorMsg } from '../../utils/content'; import { CoreDelegate, attachComponent, detachComponent } from '../../utils/framework-delegate'; import { raf } from '../../utils/helpers'; import { KEYBOARD_DID_OPEN } from '../../utils/keyboard/keyboard'; @@ -283,11 +284,11 @@ export class Modal implements ComponentInterface, OverlayInterface { @Event({ eventName: 'didDismiss' }) didDismissShorthand!: EventEmitter; @Watch('swipeToClose') - swipeToCloseChanged(enable: boolean) { + async swipeToCloseChanged(enable: boolean) { if (this.gesture) { this.gesture.enable(enable); } else if (enable) { - this.initSwipeToClose(); + await this.initSwipeToClose(); } } @@ -474,7 +475,7 @@ export class Modal implements ComponentInterface, OverlayInterface { * not run canDismiss on swipe as there would be no swipe gesture created. */ } else if (this.swipeToClose || (this.canDismiss !== undefined && this.presentingElement !== undefined)) { - this.initSwipeToClose(); + await this.initSwipeToClose(); } /* tslint:disable-next-line */ @@ -504,17 +505,27 @@ export class Modal implements ComponentInterface, OverlayInterface { this.currentTransition = undefined; } - private initSwipeToClose() { + private async initSwipeToClose() { if (getIonMode(this) !== 'ios') { return; } + const { el } = this; + // All of the elements needed for the swipe gesture // should be in the DOM and referenced by now, except // for the presenting el const animationBuilder = this.leaveAnimation || config.get('modalLeave', iosLeaveAnimation); - const ani = (this.animation = animationBuilder(this.el, { presentingEl: this.presentingElement })); - this.gesture = createSwipeToCloseGesture(this.el, ani, () => { + const ani = (this.animation = animationBuilder(el, { presentingEl: this.presentingElement })); + + const contentEl = findIonContent(el); + if (!contentEl) { + printIonContentErrorMsg(el); + return; + } + const scrollEl = await getScrollElement(contentEl); + + this.gesture = createSwipeToCloseGesture(el, contentEl, scrollEl, ani, () => { /** * While the gesture animation is finishing * it is possible for a user to tap the backdrop. diff --git a/core/src/components/modal/test/card-scroll-target/index.html b/core/src/components/modal/test/card-scroll-target/index.html new file mode 100644 index 0000000000..50fe1e7b1a --- /dev/null +++ b/core/src/components/modal/test/card-scroll-target/index.html @@ -0,0 +1,134 @@ + + + + + Modal - Card + + + + + + + + + + + + + +
+ + + Card + + + + + Card Modal + +
+
+ + + + diff --git a/core/src/components/modal/test/card-scroll-target/modal.e2e.ts b/core/src/components/modal/test/card-scroll-target/modal.e2e.ts new file mode 100644 index 0000000000..1ba057d154 --- /dev/null +++ b/core/src/components/modal/test/card-scroll-target/modal.e2e.ts @@ -0,0 +1,64 @@ +import { expect } from '@playwright/test'; +import { dragElementBy, test } from '@utils/test/playwright'; + +test.describe('card modal - scroll target', () => { + test.beforeEach(async ({ page }, testInfo) => { + test.skip(testInfo.project.metadata.mode !== 'ios', 'Card style modal is only available on iOS'); + + await page.goto('/src/components/modal/test/card-scroll-target'); + }); + test.describe('card modal: swipe to close', () => { + test('it should swipe to close when swiped on the header', async ({ page }) => { + const ionModalDidPresent = await page.spyOnEvent('ionModalDidPresent'); + const ionModalDidDismiss = await page.spyOnEvent('ionModalDidDismiss'); + + await page.click('#card'); + await ionModalDidPresent.next(); + + const header = await page.locator('ion-modal ion-header'); + await dragElementBy(header, page, 0, 500); + + await ionModalDidDismiss.next(); + }); + test('it should swipe to close when swiped on the content', async ({ page }) => { + const ionModalDidPresent = await page.spyOnEvent('ionModalDidPresent'); + const ionModalDidDismiss = await page.spyOnEvent('ionModalDidDismiss'); + + await page.click('#card'); + await ionModalDidPresent.next(); + + const content = await page.locator('ion-modal .ion-content-scroll-host'); + await dragElementBy(content, page, 0, 500); + + await ionModalDidDismiss.next(); + }); + test('it should not swipe to close when swiped on the content but the content is scrolled', async ({ page }) => { + const ionModalDidPresent = await page.spyOnEvent('ionModalDidPresent'); + + await page.click('#card'); + await ionModalDidPresent.next(); + + const modal = await page.locator('ion-modal'); + const content = (await page.$('ion-modal .ion-content-scroll-host'))!; + + await content.evaluate((el: HTMLElement) => (el.scrollTop = 500)); + + await dragElementBy(content, page, 0, 500); + + await content.waitForElementState('stable'); + + expect(modal).toBeVisible(); + }); + test('content should be scrollable after gesture ends', async ({ page }) => { + const ionModalDidPresent = await page.spyOnEvent('ionModalDidPresent'); + + await page.click('#card'); + await ionModalDidPresent.next(); + + const content = await page.locator('ion-modal .ion-content-scroll-host'); + await dragElementBy(content, page, 0, 20); + + expect(content).not.toHaveCSS('overflow', 'hidden'); + }); + }); +}); diff --git a/core/src/components/modal/test/card/index.html b/core/src/components/modal/test/card/index.html index 89b1207234..1e711a25b0 100644 --- a/core/src/components/modal/test/card/index.html +++ b/core/src/components/modal/test/card/index.html @@ -65,7 +65,39 @@ Hello World! Dismiss Modal + +
+ +

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vitae lobortis felis, eu sodales enim. Nam + risus nibh, placerat at rutrum ac, vehicula vel velit. Lorem ipsum dolor sit amet, consectetur adipiscing + elit. Vestibulum quis elementum ligula, ac aliquet nulla. Mauris non placerat mauris. Aenean dignissim lacinia + porttitor. Praesent fringilla at est et ullamcorper. In ac ante ac massa porta venenatis ut id nibh. Fusce + felis neque, aliquet in velit vitae, venenatis euismod libero. Donec vulputate, urna sed sagittis tempor, mi + arcu tristique lacus, eget fringilla urna sem eget felis. Fusce dignissim lacus a scelerisque vehicula. Nulla + nec enim nunc. Quisque nec dui eu nibh pulvinar bibendum quis ut nunc. Duis ex odio, sollicitudin ac mollis + nec, fringilla non lacus. Maecenas sed tincidunt urna. Nunc feugiat maximus venenatis. Donec porttitor, felis + eget porttitor tempor, quam nulla dapibus nisl, sit amet posuere sapien sapien malesuada tortor. Pellentesque + habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Quisque luctus, sapien nec + tincidunt efficitur, nibh turpis faucibus felis, in sodales massa augue nec erat. Morbi sollicitudin nisi ex, + et gravida nisi euismod eu. Suspendisse hendrerit dapibus orci, non viverra neque vestibulum id. Quisque vitae + interdum ligula, quis consectetur nibh. Phasellus in mi at erat ultrices semper. Fusce sollicitudin at dolor + ac lobortis. Morbi sit amet sem quis nulla pellentesque imperdiet. Nullam eu sem a enim maximus eleifend non + vulputate leo. Proin quis congue lacus. Pellentesque placerat, quam at tempus pulvinar, nisl ligula tempor + risus, quis pretium arcu odio et nulla. Nullam mollis consequat pharetra. Phasellus dictum velit sed purus + mattis maximus. In molestie eget massa ut dignissim. In a interdum elit. In finibus nibh a mauris lobortis + aliquet. Proin rutrum varius consequat. In mollis dapibus nisl, eu finibus urna viverra ac. Quisque + scelerisque nisl eu suscipit consectetur. +

+ +
+ + + + Footer + + `; // listen for close event diff --git a/core/src/components/modal/test/card/modal.e2e.ts b/core/src/components/modal/test/card/modal.e2e.ts index f9e627dbc9..940bd132b9 100644 --- a/core/src/components/modal/test/card/modal.e2e.ts +++ b/core/src/components/modal/test/card/modal.e2e.ts @@ -1,51 +1,108 @@ import { expect } from '@playwright/test'; -import { test } from '@utils/test/playwright'; +import { dragElementBy, test } from '@utils/test/playwright'; + +test.describe('card modal', () => { + test.beforeEach(async ({ page }, testInfo) => { + test.skip(testInfo.project.metadata.mode !== 'ios', 'Card style modal is only available on iOS'); -test.describe('card modal: rendering', () => { - test('should not have visual regressions', async ({ page }) => { await page.goto('/src/components/modal/test/card'); - const ionModalDidPresent = await page.spyOnEvent('ionModalDidPresent'); + }); + test.describe('card modal: rendering', () => { + test('should not have visual regressions', async ({ page }) => { + const ionModalDidPresent = await page.spyOnEvent('ionModalDidPresent'); - await page.click('#card'); + await page.click('#card'); - await ionModalDidPresent.next(); + await ionModalDidPresent.next(); - expect(await page.screenshot()).toMatchSnapshot(`modal-card-present-${page.getSnapshotSettings()}.png`); - }); - test('should not have visual regressions with custom modal', async ({ page }) => { - await page.goto('/src/components/modal/test/card'); - const ionModalDidPresent = await page.spyOnEvent('ionModalDidPresent'); + expect(await page.screenshot()).toMatchSnapshot(`modal-card-present-${page.getSnapshotSettings()}.png`); + }); + test('should not have visual regressions with custom modal', async ({ page }) => { + const ionModalDidPresent = await page.spyOnEvent('ionModalDidPresent'); - await page.click('#card-custom'); + await page.click('#card-custom'); - await ionModalDidPresent.next(); + await ionModalDidPresent.next(); - expect(await page.screenshot()).toMatchSnapshot(`modal-card-custom-present-${page.getSnapshotSettings()}.png`); - }); - test('should not have visual regressions with stacked cards', async ({ page }) => { - await page.goto('/src/components/modal/test/card'); - const ionModalDidPresent = await page.spyOnEvent('ionModalDidPresent'); + expect(await page.screenshot()).toMatchSnapshot(`modal-card-custom-present-${page.getSnapshotSettings()}.png`); + }); + test('should not have visual regressions with stacked cards', async ({ page }) => { + const ionModalDidPresent = await page.spyOnEvent('ionModalDidPresent'); - await page.click('#card'); - await ionModalDidPresent.next(); + await page.click('#card'); + await ionModalDidPresent.next(); - await page.click('.add'); - await ionModalDidPresent.next(); + await page.click('.add'); + await ionModalDidPresent.next(); - expect(await page.screenshot()).toMatchSnapshot(`modal-card-stacked-present-${page.getSnapshotSettings()}.png`); + expect(await page.screenshot()).toMatchSnapshot(`modal-card-stacked-present-${page.getSnapshotSettings()}.png`); + }); + test('should not have visual regressions with stacked custom cards', async ({ page }) => { + const ionModalDidPresent = await page.spyOnEvent('ionModalDidPresent'); + + await page.click('#card-custom'); + await ionModalDidPresent.next(); + + await page.click('.add'); + await ionModalDidPresent.next(); + + expect(await page.screenshot()).toMatchSnapshot( + `modal-card-custom-stacked-present-${page.getSnapshotSettings()}.png` + ); + }); }); - test('should not have visual regressions with stacked custom cards', async ({ page }) => { - await page.goto('/src/components/modal/test/card'); - const ionModalDidPresent = await page.spyOnEvent('ionModalDidPresent'); + test.describe('card modal: swipe to close', () => { + test('it should swipe to close when swiped on the header', async ({ page }) => { + const ionModalDidPresent = await page.spyOnEvent('ionModalDidPresent'); + const ionModalDidDismiss = await page.spyOnEvent('ionModalDidDismiss'); + + await page.click('#card'); + await ionModalDidPresent.next(); + + const header = await page.locator('ion-modal ion-header'); + await dragElementBy(header, page, 0, 500); + + await ionModalDidDismiss.next(); + }); + test('it should swipe to close when swiped on the content', async ({ page }) => { + const ionModalDidPresent = await page.spyOnEvent('ionModalDidPresent'); + const ionModalDidDismiss = await page.spyOnEvent('ionModalDidDismiss'); + + await page.click('#card'); + await ionModalDidPresent.next(); + + const content = await page.locator('ion-modal ion-content'); + await dragElementBy(content, page, 0, 500); + + await ionModalDidDismiss.next(); + }); + test('it should not swipe to close when swiped on the content but the content is scrolled', async ({ page }) => { + const ionModalDidPresent = await page.spyOnEvent('ionModalDidPresent'); + + await page.click('#card'); + await ionModalDidPresent.next(); + + const modal = await page.locator('ion-modal'); + const content = (await page.$('ion-modal ion-content'))!; + + await content.evaluate((el: HTMLIonContentElement) => el.scrollToBottom(0)); + + await dragElementBy(content, page, 0, 500); + + await content.waitForElementState('stable'); + + expect(modal).toBeVisible(); + }); + test('content should be scrollable after gesture ends', async ({ page }) => { + const ionModalDidPresent = await page.spyOnEvent('ionModalDidPresent'); - await page.click('#card-custom'); - await ionModalDidPresent.next(); + await page.click('#card'); + await ionModalDidPresent.next(); - await page.click('.add'); - await ionModalDidPresent.next(); + const content = await page.locator('ion-modal ion-content'); + await dragElementBy(content, page, 0, 20); - expect(await page.screenshot()).toMatchSnapshot( - `modal-card-custom-stacked-present-${page.getSnapshotSettings()}.png` - ); + expect(content).toHaveJSProperty('scrollY', true); + }); }); }); diff --git a/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-custom-present-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-custom-present-ios-ltr-Mobile-Chrome-linux.png index 8395f2198a..442cace5ca 100644 Binary files a/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-custom-present-ios-ltr-Mobile-Chrome-linux.png and b/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-custom-present-ios-ltr-Mobile-Chrome-linux.png differ diff --git a/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-custom-present-ios-ltr-Mobile-Safari-linux.png b/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-custom-present-ios-ltr-Mobile-Safari-linux.png index a8cb87a6b6..599ded8fbc 100644 Binary files a/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-custom-present-ios-ltr-Mobile-Safari-linux.png and b/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-custom-present-ios-ltr-Mobile-Safari-linux.png differ diff --git a/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-custom-present-ios-rtl-Mobile-Chrome-linux.png b/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-custom-present-ios-rtl-Mobile-Chrome-linux.png index 56892676f4..08ef5d3e42 100644 Binary files a/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-custom-present-ios-rtl-Mobile-Chrome-linux.png and b/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-custom-present-ios-rtl-Mobile-Chrome-linux.png differ diff --git a/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-custom-present-ios-rtl-Mobile-Safari-linux.png b/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-custom-present-ios-rtl-Mobile-Safari-linux.png index 37794c512b..0a03fb456d 100644 Binary files a/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-custom-present-ios-rtl-Mobile-Safari-linux.png and b/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-custom-present-ios-rtl-Mobile-Safari-linux.png differ diff --git a/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-custom-stacked-present-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-custom-stacked-present-ios-ltr-Mobile-Chrome-linux.png index 9ab190aa48..a2229650ff 100644 Binary files a/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-custom-stacked-present-ios-ltr-Mobile-Chrome-linux.png and b/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-custom-stacked-present-ios-ltr-Mobile-Chrome-linux.png differ diff --git a/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-custom-stacked-present-ios-ltr-Mobile-Safari-linux.png b/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-custom-stacked-present-ios-ltr-Mobile-Safari-linux.png index d174359403..ffa5dab5b0 100644 Binary files a/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-custom-stacked-present-ios-ltr-Mobile-Safari-linux.png and b/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-custom-stacked-present-ios-ltr-Mobile-Safari-linux.png differ diff --git a/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-custom-stacked-present-ios-rtl-Mobile-Chrome-linux.png b/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-custom-stacked-present-ios-rtl-Mobile-Chrome-linux.png index ba145ab6c0..1e7cd13c55 100644 Binary files a/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-custom-stacked-present-ios-rtl-Mobile-Chrome-linux.png and b/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-custom-stacked-present-ios-rtl-Mobile-Chrome-linux.png differ diff --git a/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-custom-stacked-present-ios-rtl-Mobile-Safari-linux.png b/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-custom-stacked-present-ios-rtl-Mobile-Safari-linux.png index 8a1f663228..64e9c6922c 100644 Binary files a/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-custom-stacked-present-ios-rtl-Mobile-Safari-linux.png and b/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-custom-stacked-present-ios-rtl-Mobile-Safari-linux.png differ diff --git a/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-present-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-present-ios-ltr-Mobile-Chrome-linux.png index 321897cb7f..a67913306e 100644 Binary files a/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-present-ios-ltr-Mobile-Chrome-linux.png and b/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-present-ios-ltr-Mobile-Chrome-linux.png differ diff --git a/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-present-ios-ltr-Mobile-Safari-linux.png b/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-present-ios-ltr-Mobile-Safari-linux.png index 59bb75fc02..0e619eaca8 100644 Binary files a/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-present-ios-ltr-Mobile-Safari-linux.png and b/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-present-ios-ltr-Mobile-Safari-linux.png differ diff --git a/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-present-ios-rtl-Mobile-Chrome-linux.png b/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-present-ios-rtl-Mobile-Chrome-linux.png index d38e688a74..1cb5cf9995 100644 Binary files a/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-present-ios-rtl-Mobile-Chrome-linux.png and b/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-present-ios-rtl-Mobile-Chrome-linux.png differ diff --git a/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-present-ios-rtl-Mobile-Safari-linux.png b/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-present-ios-rtl-Mobile-Safari-linux.png index e38be50a69..b0a8a8b115 100644 Binary files a/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-present-ios-rtl-Mobile-Safari-linux.png and b/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-present-ios-rtl-Mobile-Safari-linux.png differ diff --git a/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-stacked-present-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-stacked-present-ios-ltr-Mobile-Chrome-linux.png index a276bf043f..67bc355c0f 100644 Binary files a/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-stacked-present-ios-ltr-Mobile-Chrome-linux.png and b/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-stacked-present-ios-ltr-Mobile-Chrome-linux.png differ diff --git a/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-stacked-present-ios-ltr-Mobile-Safari-linux.png b/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-stacked-present-ios-ltr-Mobile-Safari-linux.png index 2fbbac0b8c..1895d76f40 100644 Binary files a/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-stacked-present-ios-ltr-Mobile-Safari-linux.png and b/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-stacked-present-ios-ltr-Mobile-Safari-linux.png differ diff --git a/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-stacked-present-ios-rtl-Mobile-Chrome-linux.png b/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-stacked-present-ios-rtl-Mobile-Chrome-linux.png index 82e6543ff7..4421459a07 100644 Binary files a/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-stacked-present-ios-rtl-Mobile-Chrome-linux.png and b/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-stacked-present-ios-rtl-Mobile-Chrome-linux.png differ diff --git a/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-stacked-present-ios-rtl-Mobile-Safari-linux.png b/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-stacked-present-ios-rtl-Mobile-Safari-linux.png index 050aa7bbf5..f435d176da 100644 Binary files a/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-stacked-present-ios-rtl-Mobile-Safari-linux.png and b/core/src/components/modal/test/card/modal.e2e.ts-snapshots/modal-card-stacked-present-ios-rtl-Mobile-Safari-linux.png differ diff --git a/core/src/utils/content/index.ts b/core/src/utils/content/index.ts index b3b3c7eb9f..7e7a88bdf4 100644 --- a/core/src/utils/content/index.ts +++ b/core/src/utils/content/index.ts @@ -13,7 +13,7 @@ const ION_CONTENT_CLASS_SELECTOR = '.ion-content-scroll-host'; */ const ION_CONTENT_SELECTOR = `${ION_CONTENT_ELEMENT_SELECTOR}, ${ION_CONTENT_CLASS_SELECTOR}`; -const isIonContent = (el: Element) => el && el.tagName === ION_CONTENT_TAG_NAME; +export const isIonContent = (el: Element) => el && el.tagName === ION_CONTENT_TAG_NAME; /** * Waits for the element host fully initialize before diff --git a/core/src/utils/test/playwright/drag-element.ts b/core/src/utils/test/playwright/drag-element.ts index 4421232662..8cfe6d36d7 100644 --- a/core/src/utils/test/playwright/drag-element.ts +++ b/core/src/utils/test/playwright/drag-element.ts @@ -1,8 +1,13 @@ -import type { Locator } from '@playwright/test'; +import type { ElementHandle, Locator } from '@playwright/test'; import type { E2EPage } from './'; -export const dragElementBy = async (el: Locator, page: E2EPage, dragByX = 0, dragByY = 0) => { +export const dragElementBy = async ( + el: Locator | ElementHandle, + page: E2EPage, + dragByX = 0, + dragByY = 0 +) => { const boundingBox = await el.boundingBox(); if (!boundingBox) {