mirror of
https://github.com/yangshun/tech-interview-handbook.git
synced 2025-07-28 12:43:12 +08:00
124 lines
3.7 KiB
JavaScript
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} />}
|
|
</>
|
|
);
|
|
}
|