diff --git a/core/src/utils/gesture/gesture-controller.ts b/core/src/utils/gesture/gesture-controller.ts index 32f381008b0..a38d69dc79f 100644 --- a/core/src/utils/gesture/gesture-controller.ts +++ b/core/src/utils/gesture/gesture-controller.ts @@ -9,7 +9,7 @@ class GestureController { * Creates a gesture delegate based on the GestureConfig passed */ createGesture(config: GestureConfig): GestureDelegate { - return new GestureDelegate(this, this.newID(), config.name, config.priority ?? 0, !!config.disableScroll); + return new GestureDelegate(this, this.newID(), config.name, config.priority ?? 0, !!config.disableScroll, config.el); } /** @@ -28,7 +28,7 @@ class GestureController { return true; } - capture(gestureName: string, id: number, priority: number): boolean { + capture(gestureName: string, id: number, priority: number, el?: Node): boolean { if (!this.start(gestureName, id, priority)) { return false; } @@ -43,7 +43,7 @@ class GestureController { this.capturedId = id; requestedStart.clear(); - const event = new CustomEvent('ionGestureCaptured', { detail: { gestureName } }); + const event = new CustomEvent('ionGestureCaptured', { detail: { gestureName, el } }); document.dispatchEvent(event); return true; } @@ -134,7 +134,8 @@ class GestureDelegate { private id: number, private name: string, priority: number, - private disableScroll: boolean + private disableScroll: boolean, + private el?: Node ) { this.priority = priority * 1000000 + id; this.ctrl = ctrl; @@ -161,7 +162,7 @@ class GestureDelegate { return false; } - const captured = this.ctrl.capture(this.name, this.id, this.priority); + const captured = this.ctrl.capture(this.name, this.id, this.priority, this.el); if (captured && this.disableScroll) { this.ctrl.disableScroll(this.id); } @@ -236,6 +237,7 @@ export interface GestureConfig { name: string; priority?: number; disableScroll?: boolean; + el?: Node; } export interface BlockerConfig { diff --git a/core/src/utils/gesture/index.ts b/core/src/utils/gesture/index.ts index 79e5ee323df..d398b6a69c0 100644 --- a/core/src/utils/gesture/index.ts +++ b/core/src/utils/gesture/index.ts @@ -52,6 +52,7 @@ export const createGesture = (config: GestureConfig): Gesture => { name: config.gestureName, priority: config.gesturePriority, disableScroll: config.disableScroll, + el: config.el, }); const pointerDown = (ev: UIEvent): boolean => { diff --git a/core/src/utils/tap-click/index.ts b/core/src/utils/tap-click/index.ts index c5a10595f47..6379ce435af 100644 --- a/core/src/utils/tap-click/index.ts +++ b/core/src/utils/tap-click/index.ts @@ -119,7 +119,19 @@ export const startTapClick = (config: Config) => { } }; - doc.addEventListener('ionGestureCaptured', cancelActive); + doc.addEventListener('ionGestureCaptured', (ev: Event) => { + const { el } = (ev as CustomEvent).detail; + /** + * Do not cancel the active ripple if the gesture was captured + * on an activatable element (e.g. ion-button). The ripple effect + * should still apply in this case. + * See https://github.com/ionic-team/ionic-framework/issues/22491 + */ + if (el instanceof Element && el.closest('.ion-activatable')) { + return; + } + cancelActive(); + }); doc.addEventListener('pointerdown', pointerDown, true); doc.addEventListener('pointerup', pointerUp, true);