diff --git a/src/components/on-this-page.tsx b/src/components/on-this-page.tsx
index 46d23cf..cd24ad7 100644
--- a/src/components/on-this-page.tsx
+++ b/src/components/on-this-page.tsx
@@ -1,8 +1,9 @@
"use client";
-import { ReactElement, useEffect, useState } from "react";
+import { ReactElement, useEffect, useRef, useState } from "react";
import { Bars3CenterLeftIcon } from "@heroicons/react/24/outline";
import Link from "next/link";
+import { cn } from "@/lib/utils";
type Header = {
id: string;
@@ -12,6 +13,10 @@ type Header = {
const OnThisPage = ({ page }: { page: DocsContentMetadata }): ReactElement => {
const [headers, setHeaders] = useState
([]);
+ const [activeHeader, setActiveHeader] = useState(
+ undefined
+ );
+ const observerRef = useRef(undefined);
useEffect(() => {
// Regular expression to match markdown headers
@@ -33,10 +38,41 @@ const OnThisPage = ({ page }: { page: DocsContentMetadata }): ReactElement => {
setHeaders(extractedHeaders);
}, [page.content]);
+ useEffect(() => {
+ // Cleanup existing observer
+ if (observerRef.current) {
+ observerRef.current.disconnect();
+ }
+
+ const observer = new IntersectionObserver(
+ (entries: IntersectionObserverEntry[]) => {
+ entries.forEach((entry: IntersectionObserverEntry) => {
+ if (entry.isIntersecting) {
+ setActiveHeader(entry.target.id);
+ }
+ });
+ },
+ { rootMargin: "0px 0px -80% 0px", threshold: 0.1 }
+ );
+ observerRef.current = observer;
+
+ // Observe all header elements
+ headers.forEach((header: Header) => {
+ const element: HTMLElement | null = document.getElementById(
+ header.id
+ );
+ if (element) {
+ observer.observe(element);
+ }
+ });
+
+ return () => observer.disconnect();
+ }, [headers]);
+
return (
-
+
{/* Title */}
-
+
On This Page
@@ -46,10 +82,17 @@ const OnThisPage = ({ page }: { page: DocsContentMetadata }): ReactElement => {
{headers.map((header: Header) => (
- {header.text}
+
+ {header.text}
+
))}