components/side-navigation.tsx (96 lines of code) (raw):
import { useRef, useEffect, useContext } from "react";
import Link from "next/link";
import { useStyletron } from "baseui";
import { Accordion, Panel } from "baseui/accordion";
import { PageContext } from "./layout";
import * as gtag from "../lib/gtag";
function SideNavigation() {
const [css, theme] = useStyletron();
const activeLink = useRef<HTMLDivElement>();
const { siteMap = [], activePage = { key: null } } = useContext(PageContext);
useEffect(() => {
if (activeLink.current && activeLink.current.scrollIntoView) {
activeLink.current.scrollIntoView({
block: "center",
inline: "center",
});
}
}, [activePage.key]);
return (
<nav
className={css({
display: "none",
[theme.mediaQuery.large]: {
position: "fixed",
top: "60px",
width: "300px",
height: "calc(100vh - 60px)",
display: "flex",
flexDirection: "column",
paddingTop: theme.sizing.scale800,
overflowY: "scroll",
/* Hide scrollbar for Chrome, Safari and Opera */
"::-webkit-scrollbar": {
display: "none",
},
scrollbarWidth: "none",
},
})}
>
<Accordion>
{siteMap.map((section) => {
return (
<Panel title={section.name} key={section.name}>
{section.children.map((page) => {
const isActive = page.key === activePage.key;
return (
<div
ref={isActive ? activeLink : null}
key={page.key}
className={css({
padding: `${theme.sizing.scale200} ${theme.sizing.scale400}`,
marginLeft: theme.sizing.scale600,
marginRight: theme.sizing.scale600,
borderRadius: "3px",
background: isActive
? theme.colors.backgroundTertiary
: "none",
})}
>
<Link href={`/[pageKey]`} as={`/${page.key}`} passHref>
<a
className={css({
...theme.typography.ParagraphMedium,
textDecoration: "none",
color: isActive
? theme.colors.contentPrimary
: theme.colors.contentTertiary,
":focus-visible": {
outline: `solid 2px ${theme.colors.accent}`,
outlineOffset: "2px",
},
":hover": {
color: theme.colors.black,
},
})}
onClick={() => {
gtag.event({
action: "click_link_sidenav",
category: "navigation",
label: page.key,
});
}}
>
{page.name}
</a>
</Link>
</div>
);
})}
</Panel>
);
})}
</Accordion>
</nav>
);
}
export default SideNavigation;