zenno: make article toc only render upon first view

This commit is contained in:
2026-05-31 20:35:02 -04:00
parent 4ea689f426
commit 825fe0f2fb

View File

@@ -10,6 +10,26 @@
let { head, children }: Props = $props(); let { head, children }: Props = $props();
let tocViewed = $state(false);
let tocElem: HTMLElement | undefined = $state();
const observeTOC: IntersectionObserverCallback = (entries, obs) => {
for (const e of entries) {
if (!e.isIntersecting) {
continue;
}
tocViewed = true;
obs.disconnect();
}
}
$effect(() => {
if (tocElem == null) {
return;
}
const obs = new IntersectionObserver(observeTOC, {rootMargin: "20% 0px"});
obs.observe(tocElem);
});
function tocClass(s: Section) { function tocClass(s: Section) {
switch (s.h) { switch (s.h) {
case 1: case 1:
@@ -32,10 +52,12 @@
{@render head()} {@render head()}
{#if sections.length > 0} {#if sections.length > 0}
<Sec h={2} id="toc" toc={false}>Table of Contents</Sec> <Sec h={2} id="toc" toc={false}>Table of Contents</Sec>
<ul class="mb-4 list-disc pl-4"> <ul class="mb-4 list-disc pl-4" bind:this={tocElem}>
{#each sections as s (s.id)} {#if tocViewed}
<li class={tocClass(s)}><a href={`#${s.id}`}>{@render s.children()}</a></li> {#each sections as s (s.id)}
{/each} <li class={tocClass(s)}><a href={`#${s.id}`}>{@render s.children()}</a></li>
{/each}
{/if}
</ul> </ul>
{/if} {/if}
{@render children()} {@render children()}