feat(ui): add article TOC and interactive VRAM calculator for Wan 2.2
Deploy / build (push) Successful in 22s

This commit is contained in:
hoelee committed 2026-10-21 06:44:04 +08:00
1 parent 0dae8b0daa
commit 2c10cad52b
4 files changed
+609 -1

No files matched your search

+143
View File
@@ -0,0 +1,143 @@
---
import type { MarkdownHeading } from 'astro';
interface Props {
headings: MarkdownHeading[];
lang?: 'en' | 'zh';
}
const { headings, lang = 'en' } = Astro.props;
// Filter for h2 and h3 headings only (level 2 & 3)
const tocHeadings = headings.filter((h) => h.depth === 2 || h.depth === 3);
const hasHeadings = tocHeadings.length >= 3;
---
{hasHeadings && (
<nav class="toc-container" aria-label={lang === 'zh' ? '文章目录' : 'Table of Contents'}>
<details class="toc-details" open>
<summary class="toc-summary">
<span class="toc-title">
<svg class="toc-icon" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<line x1="8" y1="6" x2="21" y2="6"></line>
<line x1="8" y1="12" x2="21" y2="12"></line>
<line x1="8" y1="18" x2="21" y2="18"></line>
<line x1="3" y1="6" x2="3.01" y2="6"></line>
<line x1="3" y1="12" x2="3.01" y2="12"></line>
<line x1="3" y1="18" x2="3.01" y2="18"></line>
</svg>
{lang === 'zh' ? '目录' : 'Table of Contents'}
</span>
<span class="toc-count">({tocHeadings.length})</span>
</summary>
<ul class="toc-list">
{tocHeadings.map((h) => (
<li class={`toc-item depth-${h.depth}`}>
<a href={`#${h.slug}`} class="toc-link">
{h.text}
</a>
</li>
))}
</ul>
</details>
</nav>
)}
<style>
.toc-container {
margin: 2rem 0;
padding: 0;
border-radius: var(--radius, 8px);
background: var(--surface, #16181d);
border: 1px solid var(--border, #2d3139);
overflow: hidden;
}
.toc-details {
padding: 0;
}
.toc-summary {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0.85rem 1.15rem;
font-size: 0.95rem;
font-weight: 600;
color: var(--text, #e2e8f0);
cursor: pointer;
user-select: none;
list-style: none;
transition: background 0.15s ease;
}
.toc-summary::-webkit-details-marker {
display: none;
}
.toc-summary:hover {
background: rgba(109, 141, 255, 0.06);
}
.toc-title {
display: inline-flex;
align-items: center;
gap: 0.55rem;
}
.toc-icon {
color: var(--brand, #6d8dff);
flex-shrink: 0;
}
.toc-count {
font-size: 0.82rem;
color: var(--muted, #94a3b8);
font-weight: 400;
}
.toc-list {
margin: 0;
padding: 0.5rem 1.15rem 1rem 1.15rem;
list-style: none;
border-top: 1px solid var(--border, #2d3139);
display: flex;
flex-direction: column;
gap: 0.4rem;
}
.toc-item {
font-size: 0.9rem;
line-height: 1.45;
}
.toc-item.depth-3 {
margin-left: 1.25rem;
font-size: 0.85rem;
opacity: 0.9;
}
.toc-link {
color: var(--muted, #94a3b8);
text-decoration: none;
transition: color 0.15s ease, transform 0.15s ease;
display: inline-block;
}
.toc-link:hover {
color: var(--brand, #6d8dff);
text-decoration: underline;
}
@media (max-width: 640px) {
.toc-container {
margin: 1.5rem 0;
}
.toc-summary {
padding: 0.75rem 1rem;
}
.toc-list {
padding: 0.5rem 1rem 0.85rem 1rem;
}
}
</style>