mirror of
https://github.com/facebook/docusaurus.git
synced 2025-04-29 02:08:36 +02:00
108 lines
2.7 KiB
TypeScript
108 lines
2.7 KiB
TypeScript
/**
|
|
* 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 React, {useEffect, useRef, version, type ReactNode} from 'react';
|
|
import clsx from 'clsx';
|
|
import {
|
|
useNavbarMobileSidebar,
|
|
useNavbarSecondaryMenu,
|
|
} from '@docusaurus/theme-common/internal';
|
|
import {ThemeClassNames} from '@docusaurus/theme-common';
|
|
import type {Props} from '@theme/Navbar/MobileSidebar/Layout';
|
|
|
|
// TODO Docusaurus v4: remove temporary inert workaround
|
|
// See https://github.com/facebook/react/issues/17157
|
|
// See https://github.com/radix-ui/themes/pull/509
|
|
function inertProps(inert: boolean) {
|
|
const isBeforeReact19 = parseInt(version!.split('.')[0]!, 10) < 19;
|
|
if (isBeforeReact19) {
|
|
return {inert: inert ? '' : undefined};
|
|
}
|
|
return {inert};
|
|
}
|
|
|
|
function NavbarMobileSidebarPanel({
|
|
children,
|
|
inert,
|
|
}: {
|
|
children: ReactNode;
|
|
inert: boolean;
|
|
}) {
|
|
return (
|
|
<div
|
|
className={clsx(
|
|
ThemeClassNames.layout.navbar.mobileSidebar.panel,
|
|
'navbar-sidebar__item menu',
|
|
)}
|
|
{...inertProps(inert)}>
|
|
{children}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default function NavbarMobileSidebarLayout({
|
|
header,
|
|
primaryMenu,
|
|
secondaryMenu,
|
|
}: Props): ReactNode {
|
|
const {shown: secondaryMenuShown} = useNavbarSecondaryMenu();
|
|
const navbarModalDialog = useRef<HTMLDialogElement | null>(null);
|
|
const {shown, toggle} = useNavbarMobileSidebar();
|
|
|
|
useEffect(() => {
|
|
const {current: dialogEl} = navbarModalDialog;
|
|
|
|
if (!dialogEl) {
|
|
return;
|
|
}
|
|
if (shown) {
|
|
dialogEl.showModal();
|
|
} else {
|
|
dialogEl.close();
|
|
}
|
|
});
|
|
|
|
useEffect(() => {
|
|
const {current: dialogEl} = navbarModalDialog;
|
|
|
|
function toggleOnEscape(e: {key: string}) {
|
|
if (e.key === 'Escape') {
|
|
if (shown) {
|
|
toggle();
|
|
}
|
|
}
|
|
}
|
|
|
|
dialogEl?.addEventListener('keydown', toggleOnEscape);
|
|
|
|
return () => {
|
|
dialogEl?.removeEventListener('keydown', toggleOnEscape);
|
|
};
|
|
}, [shown, toggle]);
|
|
|
|
return (
|
|
<dialog
|
|
className={clsx(
|
|
ThemeClassNames.layout.navbar.mobileSidebar.container,
|
|
'navbar-sidebar',
|
|
)}
|
|
ref={navbarModalDialog}>
|
|
{header}
|
|
<div
|
|
className={clsx('navbar-sidebar__items', {
|
|
'navbar-sidebar__items--show-secondary': secondaryMenuShown,
|
|
})}>
|
|
<NavbarMobileSidebarPanel inert={secondaryMenuShown}>
|
|
{primaryMenu}
|
|
</NavbarMobileSidebarPanel>
|
|
<NavbarMobileSidebarPanel inert={!secondaryMenuShown}>
|
|
{secondaryMenu}
|
|
</NavbarMobileSidebarPanel>
|
|
</div>
|
|
</dialog>
|
|
);
|
|
}
|