diff options
| author | Eltrac <hi@guhub.cn> | 2025-07-14 19:26:28 +0800 |
|---|---|---|
| committer | Eltrac <hi@guhub.cn> | 2025-07-14 19:26:28 +0800 |
| commit | 29af8b6c2bd89c1966512b4305af345b8ee1ef82 (patch) | |
| tree | 07a4801791db7d6a4670d53411f0689ec0090bfe /layouts/_partials/posts/toc.html | |
| parent | 44c7def3f6958550ccf965971f1819c1d6c514f1 (diff) | |
refactor: clearer division of each partial and better folder structure
Diffstat (limited to 'layouts/_partials/posts/toc.html')
| -rw-r--r-- | layouts/_partials/posts/toc.html | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/layouts/_partials/posts/toc.html b/layouts/_partials/posts/toc.html new file mode 100644 index 00000000..794328c9 --- /dev/null +++ b/layouts/_partials/posts/toc.html @@ -0,0 +1,117 @@ +{{ if .Params.toc }} +<div id="toc-container"><div id="toc">{{ .TableOfContents }}</div></div> +<style> +/* toc */ +#toc-container { + position: absolute; + bottom: 0; + right: calc(50% + var(--page-width) / 2); + left: auto; + height: 100%; + top: 12rem; + @media screen and (max-width: 1200px) { + display: none + } +} + +#toc { + /* position */ + position: sticky; + top: 3rem; + /* styling */ + font-size: 1rem; + padding: 0 2rem; + @media screen and (max-width: 1500px) { + font-size: 0.825rem; + } + + ul { + margin-block-start: 0; + margin-block-end: 0; + padding-inline-start: 1rem; + + overflow: hidden; + position: relative; + li { + list-style: none; + + & > a { + color: var(--secondary-text-color); + text-decoration: none; + transition: color .3s; + display: inline-flex; + align-items: center; + gap: .5rem; + &::before { + content: ''; + display: inline-block; + width: 1rem; + height: .3rem; + background-color: var(--block-background-color); + border-radius: .2rem; + transition: background .3s; + } + } + + /* nested list */ + ul { + max-height: 25rem; + overflow-y: auto + } + + /* active styles */ + &:not(.active) ul { + max-height: 0 + } + a:hover, + &.active > a { + color: var(--text-color); + } + + &.active > a::before { + background-color: var(--secondary-text-color); + } + } + } +} +</style> +<script> +document.addEventListener('DOMContentLoaded', () => { + const toc = document.getElementById('toc'); + if (!toc) return; + + const headings = document.querySelectorAll('h2, h3'); + const observer = new IntersectionObserver(entries => { + entries.forEach(entry => { + if (!entry.isIntersecting) return; + + const id = entry.target.id; + const tocLink = toc.querySelector(`a[href="#${id}"]`); + if (!tocLink) return; + + const listItem = tocLink.parentElement; + const isH2 = entry.target.tagName === 'H2'; + + // Clear all active states when a new H2 is encountered + if (isH2) { + toc.querySelectorAll('li.active').forEach(el => el.classList.remove('active')); + } + + // Set current item as active + listItem.classList.add('active'); + + // If this is an H3, find and activate its parent H2 + if (!isH2) { + const parentH2Item = listItem.closest('ul').previousElementSibling?.closest('li'); + if (parentH2Item) parentH2Item.classList.add('active'); + } + }); + }, { + rootMargin: '0px 0px -50% 0px', + threshold: 0.5 + }); + + headings.forEach(heading => observer.observe(heading)); +}); +</script> +{{ end }} |
