Skip to content

Commit

Permalink
docs: add scrollspy
Browse files Browse the repository at this point in the history
scroll spy and linkable headlines
  • Loading branch information
pixelass committed Jul 15, 2023
1 parent 9a58a17 commit c74d146
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 18 deletions.
1 change: 1 addition & 0 deletions docs-gui/atoms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ export const searchAtom = atom(true);
export const guideAtom = atom(false);
export const languageAtom = atom("english");
export const loadingAtom = atom(false);
export const scrollSpyAtom = atom("");
18 changes: 12 additions & 6 deletions docs-gui/components/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ import NextLink from "next/link";
import { useRouter } from "next/router";
import type { ReactNode } from "react";
import { useEffect } from "react";
import ReactMarkdown from "react-markdown";
import type { Components } from "react-markdown";
import ReactMarkdown from "react-markdown";

// @ts-ignore
import { drawerAtom, tocAtom } from "@/docs/atoms";
import { drawerAtom, tocAtom, scrollSpyAtom } from "@/docs/atoms";
// @ts-ignore
import Bot from "@/docs/components/bot";
// @ts-ignore
Expand All @@ -39,6 +39,7 @@ import Drawer from "@/docs/components/drawer";
import { components } from "@/docs/components/markdown";
// @ts-ignore
import pages from "@/docs/pages";

/* eslint-enable @typescript-eslint/ban-ts-comment */

export function Menu() {
Expand Down Expand Up @@ -80,15 +81,19 @@ export const tocComponents = {
);
},
a({ href, children }) {
const { asPath } = useRouter();
const [, hash] = asPath.split("#");
const selected = `#${hash}` === href;
const [scrollSpy, setScrollSpy] = useAtom(scrollSpyAtom);
const id = href.replace(/^#/, "");
const selected = scrollSpy === id;

return (
<NextLink passHref legacyBehavior href={href}>
<NextLink scroll passHref legacyBehavior href={href}>
<ListItemButton
selected={selected}
component="a"
target={href.startsWith("http") ? "_blank" : undefined}
onClick={() => {
setScrollSpy(id);
}}
>
{selected && (
<ListItemDecorator>
Expand Down Expand Up @@ -160,6 +165,7 @@ export function Layout({ children }: { children: ReactNode }) {
{pathname !== "/" && (
<ClickAwayListener onClickAway={closeToc}>
<Tooltip
disablePortal
open={openToc}
color="primary"
variant="outlined"
Expand Down
58 changes: 46 additions & 12 deletions docs-gui/components/markdown.tsx
Original file line number Diff line number Diff line change
@@ -1,50 +1,84 @@
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import LinkIcon from "@mui/icons-material/Link";
import { Box, Link, List, ListItem, ListItemDecorator, Typography } from "@mui/joy";
import slugify from "@sindresorhus/slugify";
import { useAtom } from "jotai";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import NextLink from "next/link";
import ReactMarkdown from "react-markdown";
import type { Components } from "react-markdown";
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import { scrollSpyAtom } from "@/docs/atoms";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import { useScrollSpy } from "@/docs/hooks/scroll-spy";

function SpyTypography({ children, ...props }) {
const id = slugify(String(children));
const [, setScrollSpy] = useAtom(scrollSpyAtom);
useScrollSpy(id);
return (
<Typography id={id} {...props}>
{children}
<NextLink
aria-label={id}
href={`#${id}`}
onClick={() => {
setScrollSpy(id);
}}
>
<LinkIcon sx={{ ml: 2, fontSize: "1rem" }} />
</NextLink>
</Typography>
);
}

export const components = {
h1({ children }) {
return (
<Typography id={slugify(String(children))} level="h1" my={2.5}>
<SpyTypography level="h1" my={2.5}>
{children}
</Typography>
</SpyTypography>
);
},
h2({ children }) {
return (
<Typography id={slugify(String(children))} level="h2" my={2}>
<SpyTypography level="h2" my={2}>
{children}
</Typography>
</SpyTypography>
);
},
h3({ children }) {
return (
<Typography id={slugify(String(children))} level="h3" my={1.5}>
<SpyTypography level="h3" my={1.5}>
{children}
</Typography>
</SpyTypography>
);
},
h4({ children }) {
return (
<Typography id={slugify(String(children))} level="h4" my={1}>
<SpyTypography level="h4" my={1}>
{children}
</Typography>
</SpyTypography>
);
},
h5({ children }) {
return (
<Typography id={slugify(String(children))} level="h5" my={1}>
<SpyTypography level="h5" my={1}>
{children}
</Typography>
</SpyTypography>
);
},
h6({ children }) {
return (
<Typography id={slugify(String(children))} level="h6" my={0.5}>
<SpyTypography level="h6" my={0.5}>
{children}
</Typography>
</SpyTypography>
);
},
p({ children }) {
Expand Down
27 changes: 27 additions & 0 deletions docs-gui/hooks/scroll-spy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { useAtom } from "jotai";
import { useEffect } from "react";

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import { scrollSpyAtom } from "@/docs/atoms";

export function useScrollSpy(id: string) {
const [, setScrollSpy] = useAtom(scrollSpyAtom);

useEffect(() => {
const intersectionObserver = new IntersectionObserver(
async entries => {
if (entries[0].intersectionRatio <= 0) {
return;
}

setScrollSpy(id);
},
{ rootMargin: "-5% 0% -95% 0%" }
);
intersectionObserver.observe(document.getElementById(id));
return () => {
intersectionObserver.unobserve(document.getElementById(id));
};
}, [id]);
}
3 changes: 3 additions & 0 deletions pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ import { CssVarsProvider, extendTheme } from "@mui/joy/styles";
import type { AppProps } from "next/app";
// @ts-ignore
import Head from "next/head";
// @ts-ignore

// @ts-ignore
// @ts-ignore
import { Layout } from "@/docs/components/layout";

/* eslint-enable @typescript-eslint/ban-ts-comment */
import "prism-theme-vars/base.css";

Expand Down

0 comments on commit c74d146

Please sign in to comment.