Statement
I have been trying to mimic the “In this section” panel from websites for my documentation route.
An example of such a website is this https://nextjs.org/docs [right pane].
The following is my implementation for it.
export default function DocsPage() {
const [tags, setTags] = useState<Element[]>();
useEffect(() => {
setTags(Array.from(document.querySelectorAll("a.custom-md-header-link-1,
a.custom-md-header-link-2, a.custom-md-header-link-3, a.custom-md-header-link-4,
a.custom-md-header-link-5, a.custom-md-header-link-6")));
}, []);
function updateChapter() {
tags?.map((element: Element) => {
const rect =element.getBoundingClientRect();
// if rect.top() < 0
// add class +".active" to the element classList
// else if it contains that classList, remove it.
});
}
updateChapter();
return (
<div className="h-[85vh] flex justify-center">
<div className="w-4/6 p-8 overflow-scroll scroll-smooth" onScroll={() => updateChapter()}>
<div className="prose text-justify">
<Markdown markdown={{
content: input
}} />
</div>
</div>
<div className="w-1/5 p-6 overflow-scroll scrollbar "
>
{
tags?.map((element) => {
const hrefTag = element.getAttribute("href");
const getHType = parseInt(element.classList[0].charAt(element.classList[0].length - 1));
const paddingLeft: number = (getHType - 1) * 10;
return (
<div className="m-2 text-gray-400"
style={{
paddingLeft: `${paddingLeft}px`
}}
key= {element.innerHTML.toString()}
>
<a href={ hrefTag!==null ? hrefTag : undefined} >{element.innerHTML}</a>
</div>
)
})
}
</div>
</div>
)
}
Explanation
I have a set of custom classes prefixed with a.custom-md-header-link-[number], where number is nothing but the h tag, i.e h1, h2, h3…
Then, everytime the user scrolls, the onScroll listener is fired and it calls the updateChapter() function which handles the logic [commented].
Problem
The problem however, is the getBoundingClientRect()
which after the initial render seems to not be able to get the coordinates (returns a 0,0,0,0 consistently).
An example snapshot of Initial Render is given below :
And the subsequent onScroll :
What is a fix for this? Also is there another way to do this feature?