diff --git a/core/src/components/modal/gestures/sheet.ts b/core/src/components/modal/gestures/sheet.ts index 2375cfd89bd..68df1a2ecaf 100644 --- a/core/src/components/modal/gestures/sheet.ts +++ b/core/src/components/modal/gestures/sheet.ts @@ -1,6 +1,6 @@ -import { isIonContent, findClosestIonContent } from '@utils/content'; +import { findClosestIonContent, isIonContent } from '@utils/content'; import { createGesture } from '@utils/gesture'; -import { clamp, raf, getElementRoot } from '@utils/helpers'; +import { clamp, getElementRoot, raf } from '@utils/helpers'; import { FOCUS_TRAP_DISABLE_CLASS } from '@utils/overlays'; import type { Animation } from '../../../interface'; @@ -83,6 +83,7 @@ export const createSheetGesture = ( let currentBreakpoint = initialBreakpoint; let offset = 0; let canDismissBlocksGesture = false; + let cachedScrollEl: HTMLElement | null = null; const canDismissMaxStep = 0.95; const maxBreakpoint = breakpoints[breakpoints.length - 1]; const minBreakpoint = breakpoints[0]; @@ -233,6 +234,17 @@ export const createSheetGesture = ( */ canDismissBlocksGesture = baseEl.canDismiss !== undefined && baseEl.canDismiss !== true && minBreakpoint === 0; + /** + * Cache the scroll element reference when the gesture starts, + * this allows us to avoid querying the DOM for the target in onMove, + * which would impact performance significantly. + */ + if (!expandToScroll) { + const targetEl = findClosestIonContent(detail.event.target! as HTMLElement); + cachedScrollEl = + targetEl && isIonContent(targetEl) ? getElementRoot(targetEl).querySelector('.inner-scroll') : targetEl; + } + /** * If expandToScroll is disabled, we need to swap * the footer visibility to the original, so if the modal @@ -267,13 +279,8 @@ export const createSheetGesture = ( * If `expandToScroll` is disabled, and an upwards swipe gesture is done within * the scrollable content, we should not allow the swipe gesture to continue. */ - if (!expandToScroll && detail.deltaY <= 0) { - const contentEl = findClosestIonContent(detail.event.target! as HTMLElement); - const scrollEl = - contentEl && isIonContent(contentEl) ? getElementRoot(contentEl).querySelector('.inner-scroll') : contentEl; - if (scrollEl) { - return; - } + if (!expandToScroll && detail.deltaY <= 0 && cachedScrollEl) { + return; } /** @@ -334,12 +341,8 @@ export const createSheetGesture = ( * function to be called if the user is trying to swipe content upwards and the content * is not scrolled to the top. */ - if (!expandToScroll && detail.deltaY <= 0 && findClosestIonContent(detail.event.target! as HTMLElement)) { - const contentEl = findClosestIonContent(detail.event.target! as HTMLElement)!; - const scrollEl = isIonContent(contentEl) ? getElementRoot(contentEl).querySelector('.inner-scroll') : contentEl; - if (scrollEl!.scrollTop > 0) { - return; - } + if (!expandToScroll && detail.deltaY <= 0 && cachedScrollEl && cachedScrollEl.scrollTop > 0) { + return; } /**