diff --git a/src/app/[[...slug]]/layout.tsx b/src/app/[[...slug]]/layout.tsx index d871cc17f..02783991c 100644 --- a/src/app/[[...slug]]/layout.tsx +++ b/src/app/[[...slug]]/layout.tsx @@ -3,7 +3,6 @@ import { Prose } from '@/components/Prose' import React from 'react' import { allDocs } from '@/content' import DocToc from '@/components/layout/DocToC' -import { Feedback } from '@/components/Feedback' import { Button } from '@/components/ui/button' import { GitHubIcon } from '@/components/icons/GitHubIcon' import Breadcrumbs from '@/components/Breadcrumbs' diff --git a/src/components/layout/DocToC.tsx b/src/components/layout/DocToC.tsx index e3c219f3f..117b5f706 100644 --- a/src/components/layout/DocToC.tsx +++ b/src/components/layout/DocToC.tsx @@ -1,20 +1,13 @@ 'use client' import type { Doc } from '@/content' -import React, { useRef } from 'react' -import { Badge } from '../ui/badge' +import { useRef, useLayoutEffect, useState, useEffect } from 'react' import Link from 'next/link' -import { FaFacebook, FaFilePdf, FaLinkedin } from 'react-icons/fa' import { DocTracingBeam } from './DocTracingBeam' -import { BASE_URL } from '@/lib/constants' -import { title } from 'radash' import { Button } from '../ui/button' import { GitHubIcon } from '../icons/GitHubIcon' - -interface Props { - doc: Doc - articleRef?: React.RefObject -} +import { useMotionValue } from 'framer-motion' +import { cn } from '@/lib/utils' interface Toc { url: string @@ -22,25 +15,70 @@ interface Toc { depth: number } -const DocToC: React.FC = ({ doc }) => { - const articleRef = useRef(null) +const DocToC = ({ doc }: { doc: Doc }) => { + const initial = 14 + const sectionSize = 28 + const offset = 10 + + const y1 = useMotionValue(0) + const y2 = useMotionValue(0) + + const [activeIndex, setActiveIndex] = useState(-1) + + useEffect(() => { + const headings = document + .querySelectorAll('h2.md-content-header') + .values() + .toArray() + + const options = { + root: null, + rootMargin: '0px', + threshold: 1, // Adjust based on when you want to highlight + } + + const observer = new IntersectionObserver((entries) => { + entries.forEach((entry) => { + if (entry.isIntersecting) { + const index = headings.findIndex( + (heading) => heading.textContent === entry.target.textContent, + ) + + y2.set(initial + (index * sectionSize + offset)) + + setActiveIndex(index) + } + }) + }, options) + + headings.forEach((h2) => observer.observe(h2)) + + return () => { + headings.forEach((h2) => observer.unobserve(h2)) + } + }, []) return ( -
+