You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

73 lines
1.7 KiB

/*
* Copyright (c) Facebook, Inc. and its affiliates.
*/
import * as React from 'react';
import {
clearAllBodyScrollLocks,
disableBodyScroll,
enableBodyScroll,
} from 'body-scroll-lock';
import {useRouter} from 'next/router';
type SidebarNav = 'root' | 'docs' | 'reference';
/**
* Menu toggle that enables body scroll locking (for
* iOS Mobile and Tablet, Android, desktop Safari/Chrome/Firefox)
* without breaking scrolling of a target
* element.
*/
export const useMenu = () => {
const [isOpen, setIsOpen] = React.useState(false);
const menuRef = React.useRef<HTMLDivElement>(null);
const router = useRouter();
const showSidebar = React.useCallback(() => {
setIsOpen(true);
if (menuRef.current != null) {
disableBodyScroll(menuRef.current);
}
}, []);
const hideSidebar = React.useCallback(() => {
setIsOpen(false);
if (menuRef.current != null) {
enableBodyScroll(menuRef.current);
}
}, []);
const toggleOpen = React.useCallback(() => {
if (isOpen) {
hideSidebar();
} else {
showSidebar();
}
}, [showSidebar, hideSidebar, isOpen]);
React.useEffect(() => {
hideSidebar();
return () => {
clearAllBodyScrollLocks();
};
}, [router.pathname, hideSidebar]);
// Avoid top-level context re-renders
return React.useMemo(
() => ({
hideSidebar,
showSidebar,
toggleOpen,
menuRef,
isOpen,
}),
[hideSidebar, showSidebar, toggleOpen, menuRef, isOpen]
);
};
export const MenuContext = React.createContext<ReturnType<typeof useMenu>>(
{} as ReturnType<typeof useMenu>
);
export function MenuProvider(props: {children: React.ReactNode}) {
return <MenuContext.Provider value={useMenu()} {...props} />;
}