mirror of
https://github.com/reactjs/react.dev.git
synced 2026-02-26 18:58:17 +00:00
Co-authored-by: Dan Abramov <dan.abramov@me.com> Co-authored-by: Sylwia Vargas <sylwia.vargas@gmail.com> Co-authored-by: Dan Lebowitz <dan.lebo@me.com> Co-authored-by: Razvan Gradinar <grazvan@fb.com> Co-authored-by: Jared Palmer <jared@palmer.net> Co-authored-by: Dane Grant <danecando@gmail.com> Co-authored-by: Dustin Goodman <dustin.s.goodman@gmail.com> Co-authored-by: Rick Hanlon <rickhanlonii@gmail.com> Co-authored-by: Maggie Appleton <maggie.fm.appleton@gmail.com> Co-authored-by: Alex Moldovan <alex.n.moldovan@gmail.com> Co-authored-by: Ives van Hoorne <ives.v.h@gmail.com> Co-authored-by: Brian Vaughn <bvaughn@fb.com> Co-authored-by: Dmitri Pavlutin <dpavlutin@gmail.com>
70 lines
1.6 KiB
TypeScript
70 lines
1.6 KiB
TypeScript
/*
|
|
* 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]);
|
|
|
|
return {
|
|
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} />;
|
|
}
|