This PR adds the ability to collapse section in the docs sidebar (which are persistent until you close the tab), and some design facelift to the docs, which makes its design close to the site as well as polishing up many elements and interactions (like moving the search to a modal and making the table of content visible in smaller breakpoints). <img width="600" height="2270" alt="Screenshot 2025-11-28 at 5 26@2x" src="https://github.com/user-attachments/assets/3a8606c6-f74f-4bd2-84c8-d7a67ff97564" /> Release Notes: - N/A
91 lines
2.6 KiB
JavaScript
91 lines
2.6 KiB
JavaScript
let scrollTimeout;
|
|
|
|
const listenActive = () => {
|
|
const elems = document.querySelector(".pagetoc").children;
|
|
[...elems].forEach((el) => {
|
|
el.addEventListener("click", (event) => {
|
|
clearTimeout(scrollTimeout);
|
|
[...elems].forEach((el) => el.classList.remove("active"));
|
|
el.classList.add("active");
|
|
// Prevent scroll updates for a short period
|
|
scrollTimeout = setTimeout(() => {
|
|
scrollTimeout = null;
|
|
}, 100); // Adjust timing as needed
|
|
});
|
|
});
|
|
};
|
|
|
|
const getPagetoc = () =>
|
|
document.querySelector(".pagetoc") || autoCreatePagetoc();
|
|
|
|
const autoCreatePagetoc = () => {
|
|
const main = document.querySelector("#content > main");
|
|
const content = Object.assign(document.createElement("div"), {
|
|
className: "content-wrap",
|
|
});
|
|
content.append(...main.childNodes);
|
|
main.prepend(content);
|
|
main.insertAdjacentHTML(
|
|
"afterbegin",
|
|
'<div class="sidetoc"><nav class="pagetoc"></nav></div>',
|
|
);
|
|
return document.querySelector(".pagetoc");
|
|
};
|
|
const updateFunction = () => {
|
|
if (scrollTimeout) return; // Skip updates if within the cooldown period from a click
|
|
const headers = [...document.getElementsByClassName("header")];
|
|
const scrolledY = window.scrollY;
|
|
let lastHeader = null;
|
|
|
|
// Find the last header that is above the current scroll position
|
|
for (let i = headers.length - 1; i >= 0; i--) {
|
|
if (scrolledY >= headers[i].offsetTop) {
|
|
lastHeader = headers[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
const pagetocLinks = [...document.querySelector(".pagetoc").children];
|
|
pagetocLinks.forEach((link) => link.classList.remove("active"));
|
|
|
|
if (lastHeader) {
|
|
const activeLink = pagetocLinks.find(
|
|
(link) => lastHeader.href === link.href,
|
|
);
|
|
if (activeLink) activeLink.classList.add("active");
|
|
}
|
|
};
|
|
|
|
window.addEventListener("load", () => {
|
|
const pagetoc = getPagetoc();
|
|
const headers = [...document.getElementsByClassName("header")];
|
|
|
|
const nonH1Headers = headers.filter(
|
|
(header) => !header.parentElement.tagName.toLowerCase().startsWith("h1"),
|
|
);
|
|
const sidetoc = document.querySelector(".sidetoc");
|
|
const tocContainer = document.querySelector(".toc-container");
|
|
|
|
if (nonH1Headers.length === 0) {
|
|
if (sidetoc) {
|
|
sidetoc.style.display = "none";
|
|
}
|
|
if (tocContainer) {
|
|
tocContainer.style.display = "none";
|
|
}
|
|
return;
|
|
}
|
|
|
|
headers.forEach((header) => {
|
|
const link = Object.assign(document.createElement("a"), {
|
|
textContent: header.text,
|
|
href: header.href,
|
|
className: `pagetoc-${header.parentElement.tagName}`,
|
|
});
|
|
pagetoc.appendChild(link);
|
|
});
|
|
updateFunction();
|
|
listenActive();
|
|
window.addEventListener("scroll", updateFunction);
|
|
});
|