Skip to content

Commit 8032308

Browse files
committed
feat: create toc component
1 parent dbf3711 commit 8032308

File tree

3 files changed

+148
-0
lines changed

3 files changed

+148
-0
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
@reference "../../styles/index.css";
2+
3+
.details {
4+
@apply my-2
5+
block
6+
rounded-md
7+
bg-neutral-200
8+
lg:hidden
9+
dark:bg-neutral-900;
10+
11+
.summary {
12+
@apply px-4
13+
py-2;
14+
}
15+
16+
.list {
17+
@apply space-y-1
18+
px-4
19+
pb-2;
20+
}
21+
22+
.link {
23+
@apply text-sm
24+
font-semibold
25+
text-neutral-900
26+
underline
27+
hover:text-neutral-700
28+
dark:text-white
29+
dark:hover:text-neutral-500;
30+
}
31+
32+
.depthThree {
33+
@apply pl-2;
34+
}
35+
36+
.depthFour {
37+
@apply pl-4;
38+
}
39+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import TableOfContents from '#ui/Common/TableOfContents';
2+
3+
import type { Meta as MetaObj, StoryObj } from '@storybook/react-webpack5';
4+
5+
type Story = StoryObj<typeof TableOfContents>;
6+
type Meta = MetaObj<typeof TableOfContents>;
7+
8+
export const Default: Story = {};
9+
10+
export const CustomDepth: Story = {
11+
args: {
12+
minDepth: 1,
13+
maxDepth: 6,
14+
},
15+
};
16+
17+
export default {
18+
component: TableOfContents,
19+
args: {
20+
headings: [
21+
{
22+
value: 'OpenSSL update assessment, and Node.js project plans',
23+
depth: 1,
24+
data: { id: 'heading-1' },
25+
},
26+
{
27+
value: 'Summary',
28+
depth: 2,
29+
data: { id: 'summary' },
30+
},
31+
{
32+
value: 'Analysis',
33+
depth: 2,
34+
data: { id: 'analysis' },
35+
},
36+
{
37+
value: 'The c_rehash script allows command injection (CVE-2022-2068)',
38+
depth: 3,
39+
data: { id: 'the_c_rehash' },
40+
},
41+
{
42+
value: 'Contact and future updates',
43+
depth: 3,
44+
data: { id: 'contact_and_future_updates' },
45+
},
46+
{
47+
value: 'Email',
48+
depth: 4,
49+
data: { id: 'email' },
50+
},
51+
{
52+
value: 'Slack',
53+
depth: 4,
54+
data: { id: 'slack' },
55+
},
56+
{
57+
value: '#node-website',
58+
depth: 5, // h5s do not get shown
59+
data: { id: 'node-website' },
60+
},
61+
],
62+
},
63+
} as Meta;
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import classNames from 'classnames';
2+
3+
import type { Heading } from '@vcarl/remark-headings';
4+
import type { FC } from 'react';
5+
6+
import styles from './index.module.css';
7+
8+
type TableOfContentsProps = {
9+
headings: Array<Heading>;
10+
minDepth?: number;
11+
maxDepth?: number;
12+
};
13+
14+
const TableOfContents: FC<TableOfContentsProps> = ({
15+
headings,
16+
minDepth = 2,
17+
maxDepth = 4,
18+
}) => {
19+
const filteredHeadings = headings.filter(
20+
({ depth }) => depth >= minDepth && depth <= maxDepth
21+
);
22+
23+
return (
24+
<details className={styles.details}>
25+
<summary className={styles.summary}>On this page</summary>
26+
<ul className={styles.list}>
27+
{filteredHeadings.map(head => (
28+
<li key={head.data?.id}>
29+
<a
30+
href={`#${head.data?.id}`}
31+
className={classNames(
32+
styles.link,
33+
head.depth === 3 && styles.depthThree,
34+
head.depth === 4 && styles.depthFour
35+
)}
36+
>
37+
{head.value}
38+
</a>
39+
</li>
40+
))}
41+
</ul>
42+
</details>
43+
);
44+
};
45+
46+
export default TableOfContents;

0 commit comments

Comments
 (0)