From 1e39647ab615106af97cdff880f8dc22a24fbeff Mon Sep 17 00:00:00 2001 From: gbanyan Date: Tue, 18 Nov 2025 23:31:52 +0800 Subject: [PATCH] Fix duplicate imports in post TOC --- components/post-toc.tsx | 65 +++++++++++++++++++++++++++++------------ 1 file changed, 47 insertions(+), 18 deletions(-) diff --git a/components/post-toc.tsx b/components/post-toc.tsx index 0483429..67cc8c8 100644 --- a/components/post-toc.tsx +++ b/components/post-toc.tsx @@ -1,6 +1,6 @@ 'use client'; -import { useEffect, useState } from 'react'; +import { useEffect, useRef, useState } from 'react'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faListUl, faCircle } from '@fortawesome/free-solid-svg-icons'; @@ -13,6 +13,9 @@ interface TocItem { export function PostToc() { const [items, setItems] = useState([]); const [activeId, setActiveId] = useState(null); + const listRef = useRef(null); + const itemRefs = useRef>({}); + const [indicator, setIndicator] = useState({ top: 0, opacity: 0 }); useEffect(() => { const headings = Array.from( @@ -50,6 +53,18 @@ export function PostToc() { return () => observer.disconnect(); }, []); + useEffect(() => { + if (!activeId || !listRef.current) { + setIndicator({ top: 0, opacity: 0 }); + return; + } + const activeEl = itemRefs.current[activeId]; + if (!activeEl) return; + const listTop = listRef.current.getBoundingClientRect().top; + const { top, height } = activeEl.getBoundingClientRect(); + setIndicator({ top: top - listTop + height / 2, opacity: 1 }); + }, [activeId, items.length]); + const handleClick = (id: string) => (event: React.MouseEvent) => { event.preventDefault(); const el = document.getElementById(id); @@ -82,24 +97,38 @@ export function PostToc() { 目錄 - + ); }