From 0f516bd23b0d965a7a6e7281c9184220c9035d5c Mon Sep 17 00:00:00 2001 From: kbot Date: Wed, 3 Jun 2026 21:52:53 -0500 Subject: [PATCH] feat: add smooth scroll animation to TOC navigation with reduced-motion support --- components/posts/TableOfContents.tsx | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/components/posts/TableOfContents.tsx b/components/posts/TableOfContents.tsx index fae7ddc..a2cbeb6 100644 --- a/components/posts/TableOfContents.tsx +++ b/components/posts/TableOfContents.tsx @@ -1,6 +1,6 @@ "use client"; -import { useEffect, useState, useRef } from "react"; +import { useEffect, useState, useRef, type MouseEvent } from "react"; interface TOCItem { id: string; @@ -55,6 +55,22 @@ export function TableOfContents() { return () => observerRef.current?.disconnect(); }, []); + const handleLinkClick = (e: MouseEvent, 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; return ( @@ -67,6 +83,7 @@ export function TableOfContents() {
  • handleLinkClick(e, heading.id)} className={`block text-sm transition-colors ${ heading.level === 3 ? "pl-3 text-ink-soft" : "text-ink" } ${activeId === heading.id ? "font-semibold text-accent" : ""}`}