feat: add smooth scroll animation to TOC navigation with reduced-motion support

This commit is contained in:
kbot
2026-06-03 21:52:53 -05:00
parent 64d9eb2474
commit 0f516bd23b

View File

@@ -1,6 +1,6 @@
"use client"; "use client";
import { useEffect, useState, useRef } from "react"; import { useEffect, useState, useRef, type MouseEvent } from "react";
interface TOCItem { interface TOCItem {
id: string; id: string;
@@ -55,6 +55,22 @@ export function TableOfContents() {
return () => observerRef.current?.disconnect(); return () => observerRef.current?.disconnect();
}, []); }, []);
const handleLinkClick = (e: MouseEvent<HTMLAnchorElement>, id: string) => {
e.preventDefault();
const target = document.getElementById(id);
if (!target) return;
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
if (prefersReducedMotion) {
window.history.pushState(null, '', `#${id}`);
target.scrollIntoView({ behavior: 'auto' });
} else {
target.scrollIntoView({ behavior: 'smooth' });
window.history.pushState(null, '', `#${id}`);
}
};
if (headings.length === 0) return null; if (headings.length === 0) return null;
return ( return (
@@ -67,6 +83,7 @@ export function TableOfContents() {
<li key={heading.id}> <li key={heading.id}>
<a <a
href={`#${heading.id}`} href={`#${heading.id}`}
onClick={(e) => handleLinkClick(e, heading.id)}
className={`block text-sm transition-colors ${ className={`block text-sm transition-colors ${
heading.level === 3 ? "pl-3 text-ink-soft" : "text-ink" heading.level === 3 ? "pl-3 text-ink-soft" : "text-ink"
} ${activeId === heading.id ? "font-semibold text-accent" : ""}`} } ${activeId === heading.id ? "font-semibold text-accent" : ""}`}