docusaurus/packages/docusaurus-theme-classic/src/theme/hooks/useScrollPosition.ts
Alexey Pyltsyn c935fe2a37
feat(v2): add back to top button (#4912)
* feat(v2): add back to top button

* Test on mobiles

* Use clean-btn class

* Fix case

* clearer useScrollPosition() hook

* fix useScrollPosition typing + dangerous 0 fallback value + refactor a bit backToTop button

* useless fallback

* Handle both browsers with/without native smooth scrollBehavior support

* fix SupportsNativeSmoothScrolling using document on SSR

* revert to smoothScrollTopPolyfill usage

Co-authored-by: slorber <lorber.sebastien@gmail.com>
2021-07-28 22:10:17 +02:00

52 lines
1.3 KiB
TypeScript

/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import {useEffect, useRef} from 'react';
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
import type {ScrollPosition} from '@theme/hooks/useScrollPosition';
const getScrollPosition = (): ScrollPosition | null => {
return ExecutionEnvironment.canUseDOM
? {
scrollX: window.pageXOffset,
scrollY: window.pageYOffset,
}
: null;
};
const useScrollPosition = (
effect: (
position: ScrollPosition,
lastPosition: ScrollPosition | null,
) => void,
deps = [],
): void => {
const lastPositionRef = useRef<ScrollPosition | null>(getScrollPosition());
const handleScroll = () => {
const currentPosition = getScrollPosition()!;
if (effect) {
effect(currentPosition, lastPositionRef.current);
}
lastPositionRef.current = currentPosition;
};
useEffect(() => {
const opts: AddEventListenerOptions & EventListenerOptions = {
passive: true,
};
handleScroll();
window.addEventListener('scroll', handleScroll, opts);
return () => window.removeEventListener('scroll', handleScroll, opts);
}, deps);
};
export default useScrollPosition;