Files
2022-03-18 08:12:15 +08:00

124 lines
3.7 KiB
JavaScript

import React, {useState} from 'react';
import clsx from 'clsx';
import {
useThemeConfig,
useAnnouncementBar,
MobileSecondaryMenuFiller,
ThemeClassNames,
useScrollPosition,
useWindowSize,
} from '@docusaurus/theme-common';
import Logo from '@theme/Logo';
import IconArrow from '@theme/IconArrow';
import {translate} from '@docusaurus/Translate';
import {DocSidebarItems} from '@theme/DocSidebarItem';
import styles from './styles.module.css';
import SidebarAd from '../../components/SidebarAd';
import CarbonAd from '../../components/CarbonAd';
function useShowAnnouncementBar() {
const {isActive} = useAnnouncementBar();
const [showAnnouncementBar, setShowAnnouncementBar] = useState(isActive);
useScrollPosition(
({scrollY}) => {
if (isActive) {
setShowAnnouncementBar(scrollY === 0);
}
},
[isActive],
);
return isActive && showAnnouncementBar;
}
function HideableSidebarButton({onClick}) {
return (
<button
type="button"
title={translate({
id: 'theme.docs.sidebar.collapseButtonTitle',
message: 'Collapse sidebar',
description: 'The title attribute for collapse button of doc sidebar',
})}
aria-label={translate({
id: 'theme.docs.sidebar.collapseButtonAriaLabel',
message: 'Collapse sidebar',
description: 'The title attribute for collapse button of doc sidebar',
})}
className={clsx(
'button button--secondary button--outline',
styles.collapseSidebarButton,
)}
onClick={onClick}>
<IconArrow className={styles.collapseSidebarButtonIcon} />
</button>
);
}
function DocSidebarDesktop({path, sidebar, onCollapse, isHidden}) {
const showAnnouncementBar = useShowAnnouncementBar();
const {
navbar: {hideOnScroll},
hideableSidebar,
} = useThemeConfig();
return (
<div
className={clsx(styles.sidebar, {
[styles.sidebarWithHideableNavbar]: hideOnScroll,
[styles.sidebarHidden]: isHidden,
})}>
{hideOnScroll && <Logo tabIndex={-1} className={styles.sidebarLogo} />}
<nav
className={clsx('menu thin-scrollbar', styles.menu, {
[styles.menuWithAnnouncementBar]: showAnnouncementBar,
})}>
<ul className={clsx(ThemeClassNames.docs.docSidebarMenu, 'menu__list')}>
<DocSidebarItems items={sidebar} activePath={path} level={1} />
</ul>
</nav>
{hideableSidebar && <HideableSidebarButton onClick={onCollapse} />}
</div>
);
}
const DocSidebarMobileSecondaryMenu = ({toggleSidebar, sidebar, path}) => {
return (
<ul className={clsx(ThemeClassNames.docs.docSidebarMenu, 'menu__list')}>
<DocSidebarItems
items={sidebar}
activePath={path}
onItemClick={() => toggleSidebar()}
level={1}
/>
<div className="margin--md">
<SidebarAd position="mobile_sidebar" />
</div>
</ul>
);
};
function DocSidebarMobile(props) {
return (
<MobileSecondaryMenuFiller
component={DocSidebarMobileSecondaryMenu}
props={props}
/>
);
}
const DocSidebarDesktopMemo = React.memo(DocSidebarDesktop);
const DocSidebarMobileMemo = React.memo(DocSidebarMobile);
export default function DocSidebar(props) {
const windowSize = useWindowSize(); // Desktop sidebar visible on hydration: need SSR rendering
const shouldRenderSidebarDesktop =
windowSize === 'desktop' || windowSize === 'ssr'; // Mobile sidebar not visible on hydration: can avoid SSR rendering
const shouldRenderSidebarMobile = windowSize === 'mobile';
return (
<>
{shouldRenderSidebarDesktop && <DocSidebarDesktopMemo {...props} />}
{shouldRenderSidebarMobile && <DocSidebarMobileMemo {...props} />}
</>
);
}