From 1e1596f471e440085bf2d90e473f0cb0c0dcf6e2 Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Mon, 10 May 2021 09:38:14 -0400 Subject: [PATCH] fix(refresher): refresher now only activates when pulling down on MD (#23283) resolves #23245 --- core/src/components/refresher/refresher.tsx | 5 +-- .../components/refresher/refresher.utils.ts | 34 ++++++++++++++----- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/core/src/components/refresher/refresher.tsx b/core/src/components/refresher/refresher.tsx index e453b49122..075590ae24 100644 --- a/core/src/components/refresher/refresher.tsx +++ b/core/src/components/refresher/refresher.tsx @@ -307,7 +307,6 @@ export class Refresher implements ComponentInterface { canStart: () => this.state !== RefresherState.Refreshing && this.state !== RefresherState.Completing && this.scrollEl!.scrollTop === 0, onStart: (ev: GestureDetail) => { ev.data = { animation: undefined, didStart: false, cancelled: false }; - this.state = RefresherState.Pulling; }, onMove: (ev: GestureDetail) => { if ((ev.velocityY < 0 && this.progress === 0 && !ev.data.didStart) || ev.data.cancelled) { @@ -318,10 +317,12 @@ export class Refresher implements ComponentInterface { if (!ev.data.didStart) { ev.data.didStart = true; + this.state = RefresherState.Pulling; + writeTask(() => this.scrollEl!.style.setProperty('--overflow', 'hidden')); const animationType = getRefresherAnimationType(contentEl); - const animation = createPullingAnimation(animationType, pullingRefresherIcon); + const animation = createPullingAnimation(animationType, pullingRefresherIcon, this.el); ev.data.animation = animation; animation.progressStart(false, 0); this.ionStart.emit(); diff --git a/core/src/components/refresher/refresher.utils.ts b/core/src/components/refresher/refresher.utils.ts index d7b073a165..dc99b659b1 100644 --- a/core/src/components/refresher/refresher.utils.ts +++ b/core/src/components/refresher/refresher.utils.ts @@ -15,8 +15,8 @@ export const getRefresherAnimationType = (contentEl: HTMLIonContentElement): Ref return hasHeader ? 'translate' : 'scale'; }; -export const createPullingAnimation = (type: RefresherAnimationType, pullingSpinner: HTMLElement) => { - return type === 'scale' ? createScaleAnimation(pullingSpinner) : createTranslateAnimation(pullingSpinner); +export const createPullingAnimation = (type: RefresherAnimationType, pullingSpinner: HTMLElement, refresherEl: HTMLElement) => { + return type === 'scale' ? createScaleAnimation(pullingSpinner, refresherEl) : createTranslateAnimation(pullingSpinner, refresherEl); }; const createBaseAnimation = (pullingRefresherIcon: HTMLElement) => { @@ -85,24 +85,42 @@ const createBaseAnimation = (pullingRefresherIcon: HTMLElement) => { return baseAnimation.addAnimation([spinnerArrowContainerAnimation, circleInnerAnimation, circleOuterAnimation]); }; -const createScaleAnimation = (pullingRefresherIcon: HTMLElement) => { - const height = pullingRefresherIcon.clientHeight; +const createScaleAnimation = (pullingRefresherIcon: HTMLElement, refresherEl: HTMLElement) => { + /** + * Do not take the height of the refresher icon + * because at this point the DOM has not updated, + * so the refresher icon is still hidden with + * display: none. + * The `ion-refresher` container height + * is roughly the amount we need to offset + * the icon by when pulling down. + */ + const height = refresherEl.clientHeight; const spinnerAnimation = createAnimation() .addElement(pullingRefresherIcon) .keyframes([ - { offset: 0, transform: `scale(0) translateY(-${height + 20}px)` }, + { offset: 0, transform: `scale(0) translateY(-${height}px)` }, { offset: 1, transform: 'scale(1) translateY(100px)' } ]); return createBaseAnimation(pullingRefresherIcon).addAnimation([spinnerAnimation]); }; -const createTranslateAnimation = (pullingRefresherIcon: HTMLElement) => { - const height = pullingRefresherIcon.clientHeight; +const createTranslateAnimation = (pullingRefresherIcon: HTMLElement, refresherEl: HTMLElement) => { + /** + * Do not take the height of the refresher icon + * because at this point the DOM has not updated, + * so the refresher icon is still hidden with + * display: none. + * The `ion-refresher` container height + * is roughly the amount we need to offset + * the icon by when pulling down. + */ + const height = refresherEl.clientHeight; const spinnerAnimation = createAnimation() .addElement(pullingRefresherIcon) .keyframes([ - { offset: 0, transform: `translateY(-${height + 20}px)` }, + { offset: 0, transform: `translateY(-${height}px)` }, { offset: 1, transform: 'translateY(100px)' } ]);