fix(theme-common): use native scrolling when smooth behavior set in CSS (#7057)

* fix(theme-common): use native scrolling when smooth behavior set in CSS

* fix

* fix again

* fix again
This commit is contained in:
Joshua Chen 2022-03-29 18:02:09 +08:00 committed by GitHub
parent 77662260f8
commit 4e45e14fdd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -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,14 +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
const SupportsNativeSmoothScrolling = false;
// const SupportsNativeSmoothScrolling =
// ExecutionEnvironment.canUseDOM &&
// 'scrollBehavior' in document.documentElement.style;
type CancelScrollTop = () => void;
function smoothScrollNative(top: number): CancelScrollTop {
@ -260,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();
@ -275,8 +265,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.
@ -296,12 +287,22 @@ export function useSmoothScrollTo(): {
cancelScroll: CancelScrollTop;
} {
const cancelRef = useRef<CancelScrollTop | null>(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
cancelRef.current = supportsNativeSmoothScrolling
? smoothScrollNative(top)
: smoothScrollPolyfill(top);
},
cancelScroll: () => cancelRef?.current,
cancelScroll: () => cancelRef.current?.(),
};
}