mirror of
https://github.com/facebook/docusaurus.git
synced 2025-06-20 11:37:52 +02:00
refactor(theme): extract plumbing code of BTT button into theme-common (#7021)
* refactor(theme): extract plumbing code of BTT button into theme-common * oops
This commit is contained in:
parent
45b7a1b7c8
commit
cb03764ce5
5 changed files with 154 additions and 115 deletions
|
@ -0,0 +1,73 @@
|
|||
/**
|
||||
* 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 {useRef, useState} from 'react';
|
||||
import {useScrollPosition, useSmoothScrollTo} from '../utils/scrollUtils';
|
||||
import {useLocationChange} from '../utils/useLocationChange';
|
||||
|
||||
/** Wires the logic for the back to top button. */
|
||||
export function useBackToTopButton({
|
||||
threshold,
|
||||
}: {
|
||||
/**
|
||||
* The minimum vertical scroll position, above which a scroll-up would not
|
||||
* cause `shown` to become `true`. This is because BTT is only useful if the
|
||||
* user is far down the page.
|
||||
*/
|
||||
threshold: number;
|
||||
}): {
|
||||
/**
|
||||
* Whether the button should be displayed. We only show if the user has
|
||||
* scrolled up and is on a vertical position greater than `threshold`.
|
||||
*/
|
||||
shown: boolean;
|
||||
/**
|
||||
* A (memoized) handle for starting the scroll, which you can directly plug
|
||||
* into the props.
|
||||
*/
|
||||
scrollToTop: () => void;
|
||||
} {
|
||||
const [shown, setShown] = useState(false);
|
||||
const isFocusedAnchor = useRef(false);
|
||||
const {startScroll, cancelScroll} = useSmoothScrollTo();
|
||||
|
||||
useScrollPosition(({scrollY: scrollTop}, lastPosition) => {
|
||||
const lastScrollTop = lastPosition?.scrollY;
|
||||
// Component is just being mounted. Not really a scroll event from the user.
|
||||
// Ignore it.
|
||||
if (!lastScrollTop) {
|
||||
return;
|
||||
}
|
||||
if (isFocusedAnchor.current) {
|
||||
// This scroll position change is triggered by navigating to an anchor.
|
||||
// Ignore it.
|
||||
isFocusedAnchor.current = false;
|
||||
} else if (scrollTop >= lastScrollTop) {
|
||||
// The user has scrolled down to "fight against" the animation. Cancel any
|
||||
// animation under progress.
|
||||
cancelScroll();
|
||||
setShown(false);
|
||||
} else if (scrollTop < threshold) {
|
||||
// Scrolled to the minimum position; hide the button.
|
||||
setShown(false);
|
||||
} else if (
|
||||
scrollTop + window.innerHeight <
|
||||
document.documentElement.scrollHeight
|
||||
) {
|
||||
setShown(true);
|
||||
}
|
||||
});
|
||||
|
||||
useLocationChange((locationChangeEvent) => {
|
||||
if (locationChangeEvent.location.hash) {
|
||||
isFocusedAnchor.current = true;
|
||||
setShown(false);
|
||||
}
|
||||
});
|
||||
|
||||
return {shown, scrollToTop: () => startScroll(0)};
|
||||
}
|
|
@ -28,13 +28,11 @@ export function useHideableNavbar(hideOnScroll: boolean): {
|
|||
}
|
||||
}, []);
|
||||
|
||||
useScrollPosition((currentPosition, lastPosition) => {
|
||||
useScrollPosition(({scrollY: scrollTop}, lastPosition) => {
|
||||
if (!hideOnScroll) {
|
||||
return;
|
||||
}
|
||||
|
||||
const scrollTop = currentPosition.scrollY;
|
||||
|
||||
// Needed mostly for handling rubber band scrolling.
|
||||
// See https://github.com/facebook/docusaurus/pull/5721
|
||||
if (scrollTop < navbarHeight.current) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue