From f9ac6bfa5ac6fd2549fe679f065fa7623785a5f9 Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Tue, 29 Mar 2022 17:13:00 +0800 Subject: [PATCH 1/4] fix(theme-common): use native scrolling when smooth behavior set in CSS --- .../src/utils/scrollUtils.tsx | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/packages/docusaurus-theme-common/src/utils/scrollUtils.tsx b/packages/docusaurus-theme-common/src/utils/scrollUtils.tsx index 88142d54f221..722c1680de0b 100644 --- a/packages/docusaurus-theme-common/src/utils/scrollUtils.tsx +++ b/packages/docusaurus-theme-common/src/utils/scrollUtils.tsx @@ -236,10 +236,12 @@ export function useScrollPositionBlocker(): { // Not all have support for smooth scrolling (particularly Safari mobile iOS) // TODO proper detection is currently unreliable! // see https://github.com/wessberg/scroll-behavior-polyfill/issues/16 -const SupportsNativeSmoothScrolling = false; -// const SupportsNativeSmoothScrolling = -// ExecutionEnvironment.canUseDOM && -// 'scrollBehavior' in document.documentElement.style; +// For now, we only use native scroll behavior if smooth is already set, because +// otherwise the polyfill produces a weird UX when both CSS and JS try to scroll +// a page, and they cancel each other. +const supportsNativeSmoothScrolling = + ExecutionEnvironment.canUseDOM && + getComputedStyle(document.documentElement).scrollBehavior === 'smooth'; type CancelScrollTop = () => void; @@ -275,8 +277,9 @@ function smoothScrollPolyfill(top: number): CancelScrollTop { /** * A "smart polyfill" of `window.scrollTo({ top, behavior: "smooth" })`. - * This currently always uses a polyfilled implementation, because native - * support detection seems unreliable. + * This currently always uses a polyfilled implementation unless + * `scroll-behavior: smooth` has been set in CSS, because native support + * detection for scroll behavior seems unreliable. * * This hook does not do anything by itself: it returns a start and a stop * handle. You can execute either handle at any time. @@ -298,7 +301,7 @@ export function useSmoothScrollTo(): { const cancelRef = useRef(null); return { startScroll: (top: number) => { - cancelRef.current = SupportsNativeSmoothScrolling + cancelRef.current = supportsNativeSmoothScrolling ? smoothScrollNative(top) : smoothScrollPolyfill(top); }, From e2b54e985b7e37f7a78815dbb33101e43c6e0610 Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Tue, 29 Mar 2022 17:28:01 +0800 Subject: [PATCH 2/4] fix --- .../src/utils/scrollUtils.tsx | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/packages/docusaurus-theme-common/src/utils/scrollUtils.tsx b/packages/docusaurus-theme-common/src/utils/scrollUtils.tsx index 722c1680de0b..de5bf926e8ca 100644 --- a/packages/docusaurus-theme-common/src/utils/scrollUtils.tsx +++ b/packages/docusaurus-theme-common/src/utils/scrollUtils.tsx @@ -16,6 +16,7 @@ import React, { } from 'react'; import {useDynamicCallback, ReactContextError} from './reactUtils'; import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment'; +import useIsBrowser from '@docusaurus/useIsBrowser'; type ScrollController = { /** A boolean ref tracking whether scroll events are enabled. */ @@ -233,16 +234,6 @@ export function useScrollPositionBlocker(): { }; } -// Not all have support for smooth scrolling (particularly Safari mobile iOS) -// TODO proper detection is currently unreliable! -// see https://github.com/wessberg/scroll-behavior-polyfill/issues/16 -// For now, we only use native scroll behavior if smooth is already set, because -// otherwise the polyfill produces a weird UX when both CSS and JS try to scroll -// a page, and they cancel each other. -const supportsNativeSmoothScrolling = - ExecutionEnvironment.canUseDOM && - getComputedStyle(document.documentElement).scrollBehavior === 'smooth'; - type CancelScrollTop = () => void; function smoothScrollNative(top: number): CancelScrollTop { @@ -299,6 +290,16 @@ export function useSmoothScrollTo(): { cancelScroll: CancelScrollTop; } { const cancelRef = useRef(null); + const isBrowser = useIsBrowser(); + // Not all have support for smooth scrolling (particularly Safari mobile iOS) + // TODO proper detection is currently unreliable! + // see https://github.com/wessberg/scroll-behavior-polyfill/issues/16 + // For now, we only use native scroll behavior if smooth is already set, + // because otherwise the polyfill produces a weird UX when both CSS and JS try + // to scroll a page, and they cancel each other. + const supportsNativeSmoothScrolling = + isBrowser && + getComputedStyle(document.documentElement).scrollBehavior === 'smooth'; return { startScroll: (top: number) => { cancelRef.current = supportsNativeSmoothScrolling From dd6c1f4d9a7270f85839e17ff433ec11092a85ee Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Tue, 29 Mar 2022 17:37:25 +0800 Subject: [PATCH 3/4] fix again --- packages/docusaurus-theme-common/src/utils/scrollUtils.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/docusaurus-theme-common/src/utils/scrollUtils.tsx b/packages/docusaurus-theme-common/src/utils/scrollUtils.tsx index de5bf926e8ca..4d161c7d8668 100644 --- a/packages/docusaurus-theme-common/src/utils/scrollUtils.tsx +++ b/packages/docusaurus-theme-common/src/utils/scrollUtils.tsx @@ -306,6 +306,6 @@ export function useSmoothScrollTo(): { ? smoothScrollNative(top) : smoothScrollPolyfill(top); }, - cancelScroll: () => cancelRef?.current, + cancelScroll: () => cancelRef.current?.(), }; } From 7bf8978586dcaa52cb0164f1a88325aea13eddc4 Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Tue, 29 Mar 2022 17:38:57 +0800 Subject: [PATCH 4/4] fix again --- packages/docusaurus-theme-common/src/utils/scrollUtils.tsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/docusaurus-theme-common/src/utils/scrollUtils.tsx b/packages/docusaurus-theme-common/src/utils/scrollUtils.tsx index 4d161c7d8668..79799c37fc24 100644 --- a/packages/docusaurus-theme-common/src/utils/scrollUtils.tsx +++ b/packages/docusaurus-theme-common/src/utils/scrollUtils.tsx @@ -253,10 +253,7 @@ function smoothScrollPolyfill(top: number): CancelScrollTop { (!isUpScroll && currentScroll < top) ) { raf = requestAnimationFrame(rafRecursion); - window.scrollTo( - 0, - Math.floor(Math.abs(currentScroll - top) * 0.85) + top, - ); + window.scrollTo(0, Math.floor((currentScroll - top) * 0.85) + top); } } rafRecursion();