Footer quotes + right-hand table of contents
- two static quotes above the name line in every footer - Toc component renders h1-h3 from Astro's render() headings as a sticky right column on >=88rem screens (hidden below); scroll-position highlighting via a small passive listener; shown only when a page has 2+ headings, so listings and short notes stay clean Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
---
|
||||
interface Props {
|
||||
headings: { depth: number; slug: string; text: string }[];
|
||||
}
|
||||
const { headings } = Astro.props;
|
||||
const shown = headings.filter((h) => h.depth <= 3);
|
||||
const min = Math.min(...shown.map((h) => h.depth));
|
||||
---
|
||||
|
||||
<nav class="toc">
|
||||
<p class="toc-title">On this page</p>
|
||||
<ul>
|
||||
{
|
||||
shown.map((h) => (
|
||||
<li class={`toc-d${h.depth - min}`}>
|
||||
<a href={'#' + h.slug}>{h.text}</a>
|
||||
</li>
|
||||
))
|
||||
}
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<script>
|
||||
// highlight the section currently in view
|
||||
const toc = document.querySelector('.toc');
|
||||
if (toc) {
|
||||
const links = [...toc.querySelectorAll('a[href^="#"]')] as HTMLAnchorElement[];
|
||||
const heads = links
|
||||
.map((a) => ({
|
||||
a,
|
||||
el: document.getElementById(decodeURIComponent(a.hash.slice(1))),
|
||||
}))
|
||||
.filter((x) => x.el);
|
||||
const update = () => {
|
||||
let cur = heads[0];
|
||||
for (const h of heads) {
|
||||
if (h.el!.getBoundingClientRect().top <= 110) cur = h;
|
||||
else break;
|
||||
}
|
||||
heads.forEach((h) => h.a.classList.toggle('toc-active', h === cur));
|
||||
};
|
||||
if (heads.length) {
|
||||
document.addEventListener('scroll', update, { passive: true });
|
||||
update();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user