in packages/docusaurus-theme-common/src/hooks/useHideableNavbar.ts [16:75]
export function useHideableNavbar(hideOnScroll: boolean): {
/** A ref to the navbar component. Plug this into the actual element. */
readonly navbarRef: (node: HTMLElement | null) => void;
/** If `false`, the navbar component should not be rendered. */
readonly isNavbarVisible: boolean;
} {
const [isNavbarVisible, setIsNavbarVisible] = useState(hideOnScroll);
const isFocusedAnchor = useRef(false);
const navbarHeight = useRef(0);
const navbarRef = useCallback((node: HTMLElement | null) => {
if (node !== null) {
navbarHeight.current = node.getBoundingClientRect().height;
}
}, []);
useScrollPosition(({scrollY: scrollTop}, lastPosition) => {
if (!hideOnScroll) {
return;
}
// Needed mostly for handling rubber band scrolling.
// See https://github.com/facebook/docusaurus/pull/5721
if (scrollTop < navbarHeight.current) {
setIsNavbarVisible(true);
return;
}
if (isFocusedAnchor.current) {
isFocusedAnchor.current = false;
return;
}
const lastScrollTop = lastPosition?.scrollY;
const documentHeight =
document.documentElement.scrollHeight - navbarHeight.current;
const windowHeight = window.innerHeight;
if (lastScrollTop && scrollTop >= lastScrollTop) {
setIsNavbarVisible(false);
} else if (scrollTop + windowHeight < documentHeight) {
setIsNavbarVisible(true);
}
});
useLocationChange((locationChangeEvent) => {
if (!hideOnScroll) {
return;
}
if (locationChangeEvent.location.hash) {
isFocusedAnchor.current = true;
setIsNavbarVisible(false);
return;
}
setIsNavbarVisible(true);
});
return {navbarRef, isNavbarVisible};
}