[site/ToC][s]: smooth scroll behavior

This commit is contained in:
olayway 2022-06-09 13:52:28 +02:00
parent 41cf2c33de
commit e63bec7fd2
2 changed files with 39 additions and 40 deletions

View File

@ -1,35 +1,43 @@
import { useState, useEffect } from "react";
/* Creates an Intersection Observer to keep track of headings intersecting
* a section of the viewport defined by the rootMargin */
const getIntersectionObserver = (callback) => {
return;
};
const useHeadingsObserver = () => {
const [activeHeading, setActiveHeading] = useState("");
const [observer, setObserver] = useState(null);
const activeHeading = "";
const timeoutId = null;
/* Runs only after the first render, in order to preserve the observer
* between component rerenderings (e.g. after activeHeading change). */
* between component rerenderings. */
useEffect(() => {
const observer = new IntersectionObserver(
(entries) => {
// entries.forEach((entry) => {
// if (entry.isIntersecting) {
// setActiveHeading(entry.target.id);
// }
// });
// highlight only the first intersecting heading in the ToC
const firstIntersectingHeading = entries.find(
(entry) => entry.isIntersecting
);
if (firstIntersectingHeading) {
setActiveHeading(firstIntersectingHeading.target.id);
const newActiveHeading = firstIntersectingHeading?.target.id;
if (!newActiveHeading || activeHeading === newActiveHeading) {
return;
}
if (timeoutId) {
clearTimeout(timeoutId);
}
timeoutId = setTimeout(() => {
// remove highlight of the previous active heading in the ToC
document
.querySelector(`.toc-link[href="#${activeHeading}"]`)
?.classList.remove("active");
// add highlight to the new active heading in the ToC
document
.querySelector(`.toc-link[href="#${newActiveHeading}"]`)
?.classList.add("active");
activeHeading = newActiveHeading;
}, 250);
},
{
root: null,
threshold: 0.55,
rootMargin: "-65px 0% -85% 0%", // 65px is a navbar height
}
);
@ -41,21 +49,6 @@ const useHeadingsObserver = () => {
};
}, []);
useEffect(() => {
if (!activeHeading) {
return;
}
const tocLink = document.querySelector(
`.toc-link[href="#${activeHeading}"]`
);
tocLink.classList.add("active");
return () => {
tocLink.classList.remove("active");
};
}, [activeHeading]);
return observer;
};

View File

@ -90,19 +90,25 @@ body {
@apply p-0;
}
.toc-link {
@apply transition-colors;
}
/* link (a) element */
.toc-item .toc-link {
@apply text-sm text-slate-400 no-underline break-normal
.toc-link {
@apply transition-colors relative text-sm text-slate-400 no-underline break-normal;
}
.toc-item .toc-link:not(.active) {
@apply hover:text-white
.toc-link:not(.active) {
@apply hover:text-white;
}
.toc-link.active {
@apply text-yellow-li
@apply text-yellow-li;
}
.toc-link::before {
position: absolute;
content: "";
@apply transition-opacity opacity-0 border-l border-yellow-li h-[110%] -top-[5%] -left-[0.5rem];
}
.toc-link.active::before {
@apply opacity-100;
}