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
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} />;
|
|
}
|
|
|