blog.z0x.ca/src/components/TableOfContents.astro
2024-09-10 10:08:41 -07:00

54 lines
1.2 KiB
Text

---
import TableOfContentsHeading from "./TableOfContentsHeading.astro";
// https://kld.dev/building-table-of-contents/
const { headings } = Astro.props;
const toc = buildToc(headings);
export interface Heading {
depth: number;
slug: string;
text: string;
}
function buildToc(headings: Heading[]) {
const toc: Heading[] = [];
const parentHeadings = new Map();
headings.forEach((h) => {
const heading = { ...h, subheadings: [] };
parentHeadings.set(heading.depth, heading);
if (heading.depth === 2) {
toc.push(heading);
} else {
parentHeadings.get(heading.depth - 1).subheadings.push(heading);
}
});
return toc;
}
---
<details
open
class="animate rounded-lg border border-black/15 dark:border-white/20"
>
<summary>Table of Contents</summary>
<nav class="">
<ul class="py-3">
{toc.map((heading) => <TableOfContentsHeading heading={heading} />)}
</ul>
</nav>
</details>
<style>
summary {
@apply cursor-pointer rounded-t-lg px-3 py-1.5 font-medium transition-colors;
}
summary:hover {
@apply bg-black/5 dark:bg-white/5;
}
details[open] summary {
@apply bg-black/5 dark:bg-white/5;
}
</style>