Yes
This commit is contained in:
65
00-Lesson-Site/src/components/Post/FloatingTOC.astro
Normal file
65
00-Lesson-Site/src/components/Post/FloatingTOC.astro
Normal file
@@ -0,0 +1,65 @@
|
||||
---
|
||||
// Path: src/components/Post/FloatingTOC.astro
|
||||
import styles from "./FloatingTOC.module.scss";
|
||||
---
|
||||
|
||||
<nav class={styles.toc} aria-label="Table of Contents">
|
||||
<ul id="toc-list"></ul>
|
||||
</nav>
|
||||
|
||||
<script>
|
||||
function generateTOC() {
|
||||
const content = document.getElementById("lesson-container");
|
||||
const list = document.getElementById("toc-list");
|
||||
|
||||
if (list) list.innerHTML = "";
|
||||
if (!content || !list) return;
|
||||
|
||||
const targets = content.querySelectorAll("[data-toc]");
|
||||
|
||||
targets.forEach((el, index) => {
|
||||
if (!el.id) el.id = `toc-item-${index}`;
|
||||
|
||||
const label = el.getAttribute("data-toc");
|
||||
const level = el.getAttribute("data-toc-level") || "1";
|
||||
|
||||
const li = document.createElement("li");
|
||||
const a = document.createElement("a");
|
||||
|
||||
// Add data attribute for CSS to target specific lengths
|
||||
li.setAttribute("data-level", level);
|
||||
|
||||
a.href = `#${el.id}`;
|
||||
// No Icon span, just the text which we will hide via CSS
|
||||
a.innerHTML = `<span class="toc-text">${label}</span>`;
|
||||
|
||||
a.addEventListener("click", (e) => {
|
||||
e.preventDefault();
|
||||
el.scrollIntoView({ behavior: "smooth", block: "center" });
|
||||
});
|
||||
|
||||
li.appendChild(a);
|
||||
list.appendChild(li);
|
||||
|
||||
const observer = new IntersectionObserver(
|
||||
(entries) => {
|
||||
entries.forEach((entry) => {
|
||||
if (entry.isIntersecting) {
|
||||
// Clear all active classes
|
||||
document.querySelectorAll("#toc-list a").forEach((link) => link.classList.remove("active"));
|
||||
// Set current active
|
||||
a.classList.add("active");
|
||||
}
|
||||
});
|
||||
},
|
||||
// Tweak: Use a 1px line exactly in the vertical center of the screen
|
||||
{ rootMargin: "-50% 0px -50% 0px", threshold: 0 }
|
||||
);
|
||||
|
||||
observer.observe(el);
|
||||
});
|
||||
}
|
||||
|
||||
generateTOC();
|
||||
document.addEventListener("astro:after-swap", generateTOC);
|
||||
</script>
|
||||
Reference in New Issue
Block a user