From 5a3fac4ab99808e79c908bb35ec518944105d456 Mon Sep 17 00:00:00 2001 From: EinfachHans Date: Tue, 27 Oct 2020 22:08:54 +0100 Subject: [PATCH 01/10] feat(refresher): animations matches latest iOS --- .../components/refresher/refresher.ios.scss | 25 +++++++++++++++++-- core/src/components/refresher/refresher.tsx | 8 +++--- .../components/refresher/refresher.utils.ts | 6 ++--- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/core/src/components/refresher/refresher.ios.scss b/core/src/components/refresher/refresher.ios.scss index cc6a925e3f2..a542dfcc5d6 100644 --- a/core/src/components/refresher/refresher.ios.scss +++ b/core/src/components/refresher/refresher.ios.scss @@ -30,7 +30,7 @@ ion-refresher.refresher-native { display: block; z-index: 1; - + ion-spinner { @include margin(0, auto, 0, auto); } @@ -41,6 +41,7 @@ ion-refresher.refresher-native { --refreshing-rotation-duration: 2s; display: none; animation: var(--refreshing-rotation-duration) ease-out refresher-rotate forwards; + animation-delay: 250ms; } .refresher-refreshing { display: none; @@ -67,6 +68,16 @@ ion-refresher.refresher-native { } } +.refresher-native.refresher-completing{ + .refresher-refreshing ion-spinner { + animation: 200ms linear refresher-scale forwards; + } + + .refresher-refreshing-icon { + transform: unset; + } +} + @keyframes refresher-pop { 0% { transform: scale(1); @@ -88,4 +99,14 @@ ion-refresher.refresher-native { to { transform: rotate(180deg); } -} \ No newline at end of file +} + +@keyframes refresher-scale { + from { + transform: scale(1) rotate(0deg); + } + + to { + transform: scale(0) rotate(180deg); + } +} diff --git a/core/src/components/refresher/refresher.tsx b/core/src/components/refresher/refresher.tsx index fd9ebf6e67d..36ee28e5777 100644 --- a/core/src/components/refresher/refresher.tsx +++ b/core/src/components/refresher/refresher.tsx @@ -147,7 +147,7 @@ export class Refresher implements ComponentInterface { this.state = state; if (getIonMode(this) === 'ios') { - await translateElement(el, undefined); + await translateElement(el, undefined, 400); } else { await transitionEndAsync(this.el.querySelector('.refresher-refreshing-icon'), 200); } @@ -231,8 +231,10 @@ export class Refresher implements ComponentInterface { } } } else { - this.state = RefresherState.Pulling; - handleScrollWhilePulling(pullingSpinner, ticks, opacity, currentTickToShow); + if (!this.didRefresh) { + this.state = RefresherState.Pulling; + handleScrollWhilePulling(pullingSpinner, ticks, opacity, currentTickToShow); + } } }); }; diff --git a/core/src/components/refresher/refresher.utils.ts b/core/src/components/refresher/refresher.utils.ts index 9c7b3154b7d..867fb92c31e 100644 --- a/core/src/components/refresher/refresher.utils.ts +++ b/core/src/components/refresher/refresher.utils.ts @@ -145,13 +145,13 @@ export const handleScrollWhileRefreshing = ( }); }; -export const translateElement = (el?: HTMLElement, value?: string) => { +export const translateElement = (el?: HTMLElement, value?: string, duration = 200) => { if (!el) { return Promise.resolve(); } - const trans = transitionEndAsync(el, 200); + const trans = transitionEndAsync(el, duration); writeTask(() => { - el.style.setProperty('transition', '0.2s all ease-out'); + el.style.setProperty('transition', `${duration}ms all ease-out`); if (value === undefined) { el.style.removeProperty('transform'); From e63e9d5e1ec27797445acffa3e721c15562c3643 Mon Sep 17 00:00:00 2001 From: EinfachHans Date: Thu, 5 Nov 2020 11:14:05 +0100 Subject: [PATCH 02/10] ios native refresher color grey --- core/src/components/refresher/refresher.ios.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/src/components/refresher/refresher.ios.scss b/core/src/components/refresher/refresher.ios.scss index a542dfcc5d6..dce84e49cc7 100644 --- a/core/src/components/refresher/refresher.ios.scss +++ b/core/src/components/refresher/refresher.ios.scss @@ -47,6 +47,10 @@ ion-refresher.refresher-native { display: none; animation: 250ms linear refresher-pop forwards; } + + ion-spinner { + color: grey; + } } .refresher-native.refresher-refreshing, From 264c604bd7e38c3e042ccb889bdd1f78d3d2411b Mon Sep 17 00:00:00 2001 From: EinfachHans Date: Thu, 5 Nov 2020 11:40:38 +0100 Subject: [PATCH 03/10] fade in every tick --- core/src/components/refresher/refresher.tsx | 22 ++++++++++++++----- .../components/refresher/refresher.utils.ts | 11 +++++----- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/core/src/components/refresher/refresher.tsx b/core/src/components/refresher/refresher.tsx index 36ee28e5777..bfaeb50ac6b 100644 --- a/core/src/components/refresher/refresher.tsx +++ b/core/src/components/refresher/refresher.tsx @@ -6,7 +6,17 @@ import { getTimeGivenProgression } from '../../utils/animation/cubic-bezier'; import { clamp, getElementRoot, raf } from '../../utils/helpers'; import { hapticImpact } from '../../utils/native/haptic'; -import { createPullingAnimation, createSnapBackAnimation, getRefresherAnimationType, handleScrollWhilePulling, handleScrollWhileRefreshing, setSpinnerOpacity, shouldUseNativeRefresher, transitionEndAsync, translateElement } from './refresher.utils'; +import { + createPullingAnimation, + createSnapBackAnimation, + getRefresherAnimationType, + handleScrollWhilePulling, + handleScrollWhileRefreshing, + setSpinnerOpacity, + shouldUseNativeRefresher, + transitionEndAsync, + translateElement +} from './refresher.utils'; @Component({ tag: 'ion-refresher', @@ -207,9 +217,11 @@ export class Refresher implements ComponentInterface { } // delay showing the next tick marks until user has pulled 30px - const opacity = clamp(0, Math.abs(scrollTop) / refresherHeight, 0.99); - const pullAmount = this.progress = clamp(0, (Math.abs(scrollTop) - 30) / MAX_PULL, 1); - const currentTickToShow = clamp(0, Math.floor(pullAmount * NUM_TICKS), NUM_TICKS - 1); + const pullAmount = this.progress = clamp(0, (Math.abs(scrollTop) - 10) / MAX_PULL, 1); + const computedTicksAmount = pullAmount * NUM_TICKS; + const computedTicksToShow = Math.floor(computedTicksAmount); + const currentTickToShow = clamp(0, computedTicksToShow, NUM_TICKS - 1); + const lastTickOpacity = computedTicksAmount - computedTicksToShow const shouldShowRefreshingSpinner = this.state === RefresherState.Refreshing || currentTickToShow === NUM_TICKS - 1; if (shouldShowRefreshingSpinner) { @@ -233,7 +245,7 @@ export class Refresher implements ComponentInterface { } else { if (!this.didRefresh) { this.state = RefresherState.Pulling; - handleScrollWhilePulling(pullingSpinner, ticks, opacity, currentTickToShow); + handleScrollWhilePulling(ticks, currentTickToShow, lastTickOpacity); } } }); diff --git a/core/src/components/refresher/refresher.utils.ts b/core/src/components/refresher/refresher.utils.ts index 867fb92c31e..209c0e77b3c 100644 --- a/core/src/components/refresher/refresher.utils.ts +++ b/core/src/components/refresher/refresher.utils.ts @@ -123,14 +123,15 @@ export const setSpinnerOpacity = (spinner: HTMLElement, opacity: number) => { }; export const handleScrollWhilePulling = ( - spinner: HTMLElement, ticks: NodeListOf, - opacity: number, - currentTickToShow: number + currentTickToShow: number, + lastTickOpacity: number ) => { writeTask(() => { - setSpinnerOpacity(spinner, opacity); - ticks.forEach((el, i) => el.style.setProperty('opacity', (i <= currentTickToShow) ? '0.99' : '0')); + ticks.forEach((el, i) => { + const op = i < currentTickToShow ? ('0.99') : (i === currentTickToShow ? `${lastTickOpacity}` : '0'); + el.style.setProperty('opacity', op); + }); }); }; From d65bc45a2780934b0f73dcdf881b299de5328e74 Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Tue, 16 Feb 2021 15:28:52 -0500 Subject: [PATCH 04/10] improve pulling animation --- .../components/refresher/refresher.ios.scss | 48 +++++++------------ .../refresher/refresher.ios.vars.scss | 13 ++++- core/src/components/refresher/refresher.scss | 2 +- core/src/components/refresher/refresher.tsx | 18 +++---- .../components/refresher/refresher.utils.ts | 15 ++++-- 5 files changed, 45 insertions(+), 51 deletions(-) diff --git a/core/src/components/refresher/refresher.ios.scss b/core/src/components/refresher/refresher.ios.scss index dce84e49cc7..c1c4246ca79 100644 --- a/core/src/components/refresher/refresher.ios.scss +++ b/core/src/components/refresher/refresher.ios.scss @@ -36,21 +36,21 @@ ion-refresher.refresher-native { } } -.refresher-native { - .refresher-refreshing ion-spinner { - --refreshing-rotation-duration: 2s; - display: none; - animation: var(--refreshing-rotation-duration) ease-out refresher-rotate forwards; - animation-delay: 250ms; - } - .refresher-refreshing { - display: none; - animation: 250ms linear refresher-pop forwards; - } +.refresher-native .refresher-refreshing ion-spinner { + --refreshing-rotation-duration: 2s; + display: none; + animation: var(--refreshing-rotation-duration) ease-out refresher-rotate forwards; +} +.refresher-native .refresher-refreshing { + display: none; + animation: 250ms linear refresher-pop forwards; +} - ion-spinner { - color: grey; - } +.refresher-native ion-spinner { + color: #{$refresher-ios-native-spinner-color}; + + width: #{$refresher-ios-native-spinner-width}; + height: #{$refresher-ios-native-spinner-height}; } .refresher-native.refresher-refreshing, @@ -72,14 +72,10 @@ ion-refresher.refresher-native { } } -.refresher-native.refresher-completing{ - .refresher-refreshing ion-spinner { - animation: 200ms linear refresher-scale forwards; - } +.refresher-native.refresher-completing ion-refresher-content .refresher-refreshing-icon { + transition: 300ms; - .refresher-refreshing-icon { - transform: unset; - } + transform: scale(0) rotate(180deg); } @keyframes refresher-pop { @@ -104,13 +100,3 @@ ion-refresher.refresher-native { transform: rotate(180deg); } } - -@keyframes refresher-scale { - from { - transform: scale(1) rotate(0deg); - } - - to { - transform: scale(0) rotate(180deg); - } -} diff --git a/core/src/components/refresher/refresher.ios.vars.scss b/core/src/components/refresher/refresher.ios.vars.scss index 5f98c15b180..fbc1f7c432a 100644 --- a/core/src/components/refresher/refresher.ios.vars.scss +++ b/core/src/components/refresher/refresher.ios.vars.scss @@ -1,7 +1,16 @@ @import "../../themes/ionic.globals.ios"; /// @prop - Color of the refresher icon -$refresher-ios-icon-color: $text-color !default; +$refresher-ios-icon-color: $text-color !default; /// @prop - Text color of the refresher content -$refresher-ios-text-color: $text-color !default; +$refresher-ios-text-color: $text-color !default; + +/// @prop - Color of the native refresher spinner +$refresher-ios-native-spinner-color: var(--ion-color-step-450, #747577) !default; + +/// @prop - Width of the native refresher spinner +$refresher-ios-native-spinner-width: 32px !default; + +/// @prop - Height of the native refresher spinner +$refresher-ios-native-spinner-height: 32px !default; diff --git a/core/src/components/refresher/refresher.scss b/core/src/components/refresher/refresher.scss index b0b4c5febcd..29949ebc1c5 100644 --- a/core/src/components/refresher/refresher.scss +++ b/core/src/components/refresher/refresher.scss @@ -112,4 +112,4 @@ ion-refresher-content .arrow-container { .refresher-pulling-text, .refresher-refreshing-text { display: none; } -} \ No newline at end of file +} diff --git a/core/src/components/refresher/refresher.tsx b/core/src/components/refresher/refresher.tsx index c7b669bcae9..4828c95646f 100644 --- a/core/src/components/refresher/refresher.tsx +++ b/core/src/components/refresher/refresher.tsx @@ -157,7 +157,7 @@ export class Refresher implements ComponentInterface { this.state = state; if (getIonMode(this) === 'ios') { - await translateElement(el, undefined, 400); + await translateElement(el, undefined, 300); } else { await transitionEndAsync(this.el.querySelector('.refresher-refreshing-icon'), 200); } @@ -175,7 +175,7 @@ export class Refresher implements ComponentInterface { private async setupiOSNativeRefresher(pullingSpinner: HTMLIonSpinnerElement, refreshingSpinner: HTMLIonSpinnerElement) { this.elementToTransform = this.scrollEl!; const ticks = pullingSpinner.shadowRoot!.querySelectorAll('svg'); - let MAX_PULL = this.scrollEl!.clientHeight * 0.16; + let MAX_PULL = this.scrollEl!.clientHeight * 0.15; const NUM_TICKS = ticks.length; writeTask(() => ticks.forEach(el => el.style.setProperty('animation', 'none'))); @@ -217,12 +217,8 @@ export class Refresher implements ComponentInterface { } // delay showing the next tick marks until user has pulled 30px - const pullAmount = this.progress = clamp(0, (Math.abs(scrollTop) - 10) / MAX_PULL, 1); - const computedTicksAmount = pullAmount * NUM_TICKS; - const computedTicksToShow = Math.floor(computedTicksAmount); - const currentTickToShow = clamp(0, computedTicksToShow, NUM_TICKS - 1); - const lastTickOpacity = computedTicksAmount - computedTicksToShow - const shouldShowRefreshingSpinner = this.state === RefresherState.Refreshing || currentTickToShow === NUM_TICKS - 1; + const pullAmount = this.progress = clamp(0, (Math.abs(scrollTop) - 30) / MAX_PULL, 1); + const shouldShowRefreshingSpinner = this.state === RefresherState.Refreshing || pullAmount === 1; if (shouldShowRefreshingSpinner) { if (this.pointerDown) { @@ -243,10 +239,8 @@ export class Refresher implements ComponentInterface { } } } else { - if (!this.didRefresh) { - this.state = RefresherState.Pulling; - handleScrollWhilePulling(ticks, currentTickToShow, lastTickOpacity); - } + this.state = RefresherState.Pulling; + handleScrollWhilePulling(ticks, NUM_TICKS, pullAmount); } }); }; diff --git a/core/src/components/refresher/refresher.utils.ts b/core/src/components/refresher/refresher.utils.ts index eaafe02a563..9d36d27c279 100644 --- a/core/src/components/refresher/refresher.utils.ts +++ b/core/src/components/refresher/refresher.utils.ts @@ -1,7 +1,7 @@ import { writeTask } from '@stencil/core'; import { createAnimation } from '../../utils/animation/animation'; -import { componentOnReady } from '../../utils/helpers'; +import { clamp, componentOnReady } from '../../utils/helpers'; import { isPlatform } from '../../utils/platform'; // MD Native Refresher @@ -125,13 +125,18 @@ export const setSpinnerOpacity = (spinner: HTMLElement, opacity: number) => { export const handleScrollWhilePulling = ( ticks: NodeListOf, - currentTickToShow: number, - lastTickOpacity: number + numTicks: number, + pullAmount: number ) => { + const max = 1; writeTask(() => { ticks.forEach((el, i) => { - const op = i < currentTickToShow ? ('0.99') : (i === currentTickToShow ? `${lastTickOpacity}` : '0'); - el.style.setProperty('opacity', op); + const min = i * (max / numTicks); + const range = max - min; + const start = pullAmount - min; + const progression = clamp(0, start / range, 1); + + el.style.setProperty('opacity', progression.toString()); }); }); }; From 9c89bc5ee80ab6fcbb79f0ce8bb02ff676db6b75 Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Tue, 16 Feb 2021 15:33:13 -0500 Subject: [PATCH 05/10] Add comments --- core/src/components/refresher/refresher.utils.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/src/components/refresher/refresher.utils.ts b/core/src/components/refresher/refresher.utils.ts index 9d36d27c279..bcf7c905518 100644 --- a/core/src/components/refresher/refresher.utils.ts +++ b/core/src/components/refresher/refresher.utils.ts @@ -131,6 +131,12 @@ export const handleScrollWhilePulling = ( const max = 1; writeTask(() => { ticks.forEach((el, i) => { + /** + * Compute the opacity of each tick + * mark as a percentage of the pullAmount + * offset by max / numTicks so + * the tick marks are shown staggered. + */ const min = i * (max / numTicks); const range = max - min; const start = pullAmount - min; From 0cfeab770f0cc0ed3f9244a821e82a5d8ed2ff3c Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Wed, 17 Feb 2021 12:47:49 -0500 Subject: [PATCH 06/10] lint --- core/src/components/refresher/refresher.ios.scss | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/src/components/refresher/refresher.ios.scss b/core/src/components/refresher/refresher.ios.scss index c1c4246ca79..a29d743d53f 100644 --- a/core/src/components/refresher/refresher.ios.scss +++ b/core/src/components/refresher/refresher.ios.scss @@ -47,10 +47,10 @@ ion-refresher.refresher-native { } .refresher-native ion-spinner { - color: #{$refresher-ios-native-spinner-color}; - width: #{$refresher-ios-native-spinner-width}; height: #{$refresher-ios-native-spinner-height}; + + color: #{$refresher-ios-native-spinner-color}; } .refresher-native.refresher-refreshing, @@ -73,9 +73,9 @@ ion-refresher.refresher-native { } .refresher-native.refresher-completing ion-refresher-content .refresher-refreshing-icon { - transition: 300ms; - transform: scale(0) rotate(180deg); + + transition: 300ms; } @keyframes refresher-pop { From 4a4b35d0746339534102298a920f3a56b2225267 Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Wed, 17 Feb 2021 15:07:51 -0500 Subject: [PATCH 07/10] bug fixes --- core/src/components/refresher/refresher.tsx | 30 +++++++++++---------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/core/src/components/refresher/refresher.tsx b/core/src/components/refresher/refresher.tsx index 4828c95646f..4705ea25d17 100644 --- a/core/src/components/refresher/refresher.tsx +++ b/core/src/components/refresher/refresher.tsx @@ -189,18 +189,13 @@ export class Refresher implements ComponentInterface { const scrollTop = this.scrollEl!.scrollTop; const refresherHeight = this.el.clientHeight; - if (scrollTop > 0) { - /** - * If refresher is refreshing and user tries to scroll - * progressively fade refresher out/in - */ - if (this.state === RefresherState.Refreshing) { - const ratio = clamp(0, scrollTop / (refresherHeight * 0.5), 1); - writeTask(() => setSpinnerOpacity(refreshingSpinner, 1 - ratio)); - return; - } - - writeTask(() => setSpinnerOpacity(pullingSpinner, 0)); + /** + * If refresher is refreshing and user tries to scroll + * progressively fade refresher out/in + */ + if (scrollTop > 0 && this.state === RefresherState.Refreshing) { + const ratio = clamp(0, scrollTop / (refresherHeight * 0.5), 1); + writeTask(() => setSpinnerOpacity(refreshingSpinner, 1 - ratio)); return; } @@ -216,8 +211,15 @@ export class Refresher implements ComponentInterface { } } - // delay showing the next tick marks until user has pulled 30px - const pullAmount = this.progress = clamp(0, (Math.abs(scrollTop) - 30) / MAX_PULL, 1); + /** + * We want to delay the start of this gesture by ~30px + * when initially pulling down so the refresher does not + * overlap with the content. But when letting go of the + * gesture before the refresher completes, we want the + * refresher tick marks to quickly fade out. + */ + const offset = (this.didStart) ? 30 : 0; + const pullAmount = this.progress = clamp(0, (Math.abs(scrollTop) - offset) / MAX_PULL, 1); const shouldShowRefreshingSpinner = this.state === RefresherState.Refreshing || pullAmount === 1; if (shouldShowRefreshingSpinner) { From 5d42b334979e6c315fbc33c88d2642a17ef83ec9 Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Wed, 17 Feb 2021 15:10:35 -0500 Subject: [PATCH 08/10] undo max pull change --- core/src/components/refresher/refresher.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/components/refresher/refresher.tsx b/core/src/components/refresher/refresher.tsx index 4705ea25d17..67efc76fe6b 100644 --- a/core/src/components/refresher/refresher.tsx +++ b/core/src/components/refresher/refresher.tsx @@ -175,7 +175,7 @@ export class Refresher implements ComponentInterface { private async setupiOSNativeRefresher(pullingSpinner: HTMLIonSpinnerElement, refreshingSpinner: HTMLIonSpinnerElement) { this.elementToTransform = this.scrollEl!; const ticks = pullingSpinner.shadowRoot!.querySelectorAll('svg'); - let MAX_PULL = this.scrollEl!.clientHeight * 0.15; + let MAX_PULL = this.scrollEl!.clientHeight * 0.16; const NUM_TICKS = ticks.length; writeTask(() => ticks.forEach(el => el.style.setProperty('animation', 'none'))); From 4fa6251e85ddb4e3e61822039297c870efeac669 Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Wed, 17 Feb 2021 15:23:00 -0500 Subject: [PATCH 09/10] Revert "bug fixes" This reverts commit 4a4b35d0746339534102298a920f3a56b2225267. --- core/src/components/refresher/refresher.tsx | 30 ++++++++++----------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/core/src/components/refresher/refresher.tsx b/core/src/components/refresher/refresher.tsx index 67efc76fe6b..7c9f6115966 100644 --- a/core/src/components/refresher/refresher.tsx +++ b/core/src/components/refresher/refresher.tsx @@ -189,13 +189,18 @@ export class Refresher implements ComponentInterface { const scrollTop = this.scrollEl!.scrollTop; const refresherHeight = this.el.clientHeight; - /** - * If refresher is refreshing and user tries to scroll - * progressively fade refresher out/in - */ - if (scrollTop > 0 && this.state === RefresherState.Refreshing) { - const ratio = clamp(0, scrollTop / (refresherHeight * 0.5), 1); - writeTask(() => setSpinnerOpacity(refreshingSpinner, 1 - ratio)); + if (scrollTop > 0) { + /** + * If refresher is refreshing and user tries to scroll + * progressively fade refresher out/in + */ + if (this.state === RefresherState.Refreshing) { + const ratio = clamp(0, scrollTop / (refresherHeight * 0.5), 1); + writeTask(() => setSpinnerOpacity(refreshingSpinner, 1 - ratio)); + return; + } + + writeTask(() => setSpinnerOpacity(pullingSpinner, 0)); return; } @@ -211,15 +216,8 @@ export class Refresher implements ComponentInterface { } } - /** - * We want to delay the start of this gesture by ~30px - * when initially pulling down so the refresher does not - * overlap with the content. But when letting go of the - * gesture before the refresher completes, we want the - * refresher tick marks to quickly fade out. - */ - const offset = (this.didStart) ? 30 : 0; - const pullAmount = this.progress = clamp(0, (Math.abs(scrollTop) - offset) / MAX_PULL, 1); + // delay showing the next tick marks until user has pulled 30px + const pullAmount = this.progress = clamp(0, (Math.abs(scrollTop) - 30) / MAX_PULL, 1); const shouldShowRefreshingSpinner = this.state === RefresherState.Refreshing || pullAmount === 1; if (shouldShowRefreshingSpinner) { From fc147cdbce720ca92b2bd4e140c54fbf71148284 Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Wed, 17 Feb 2021 15:25:20 -0500 Subject: [PATCH 10/10] more bug fixes --- core/src/components/refresher/refresher.tsx | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/core/src/components/refresher/refresher.tsx b/core/src/components/refresher/refresher.tsx index 7c9f6115966..08af0a2703e 100644 --- a/core/src/components/refresher/refresher.tsx +++ b/core/src/components/refresher/refresher.tsx @@ -200,7 +200,6 @@ export class Refresher implements ComponentInterface { return; } - writeTask(() => setSpinnerOpacity(pullingSpinner, 0)); return; } @@ -216,8 +215,15 @@ export class Refresher implements ComponentInterface { } } - // delay showing the next tick marks until user has pulled 30px - const pullAmount = this.progress = clamp(0, (Math.abs(scrollTop) - 30) / MAX_PULL, 1); + /** + * We want to delay the start of this gesture by ~30px + * when initially pulling down so the refresher does not + * overlap with the content. But when letting go of the + * gesture before the refresher completes, we want the + * refresher tick marks to quickly fade out. + */ + const offset = (this.didStart) ? 30 : 0; + const pullAmount = this.progress = clamp(0, (Math.abs(scrollTop) - offset) / MAX_PULL, 1); const shouldShowRefreshingSpinner = this.state === RefresherState.Refreshing || pullAmount === 1; if (shouldShowRefreshingSpinner) {