Skip to content

Commit 33c03a8

Browse files
jonwigginsclaude
andcommitted
Fix: Auto-update TOC highlight on scroll in Learn page
Added Intersection Observer to track which section is currently visible and automatically update the active section highlight in the table of contents as the user scrolls. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 0ccd4a1 commit 33c03a8

1 file changed

Lines changed: 33 additions & 3 deletions

File tree

src/pages/LearnPage.tsx

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { useState } from 'react';
2-
import { ChevronRight, Terminal, Cpu, Shield, Zap, Users, Database, FileCode, BookOpen } from 'lucide-react';
1+
import { useState, useEffect, useRef } from 'react';
2+
import { Terminal, Cpu, Shield, Zap, Users, Database, FileCode, BookOpen } from 'lucide-react';
33
import { CodeBlock } from '../components/CodeBlock';
44
import clsx from 'clsx';
55

@@ -56,6 +56,36 @@ function Callout({ type, title, children }: { type: 'info' | 'warning' | 'tip';
5656

5757
export function LearnPage() {
5858
const [activeSection, setActiveSection] = useState('introduction');
59+
const mainRef = useRef<HTMLElement>(null);
60+
61+
// Track which section is currently visible using Intersection Observer
62+
useEffect(() => {
63+
const observerOptions = {
64+
root: mainRef.current,
65+
rootMargin: '-20% 0px -70% 0px', // Trigger when section is in upper portion of viewport
66+
threshold: 0,
67+
};
68+
69+
const observerCallback: IntersectionObserverCallback = (entries) => {
70+
entries.forEach((entry) => {
71+
if (entry.isIntersecting) {
72+
setActiveSection(entry.target.id);
73+
}
74+
});
75+
};
76+
77+
const observer = new IntersectionObserver(observerCallback, observerOptions);
78+
79+
// Observe all section elements
80+
sections.forEach((section) => {
81+
const element = document.getElementById(section.id);
82+
if (element) {
83+
observer.observe(element);
84+
}
85+
});
86+
87+
return () => observer.disconnect();
88+
}, []);
5989

6090
const scrollToSection = (id: string) => {
6191
setActiveSection(id);
@@ -94,7 +124,7 @@ export function LearnPage() {
94124
</aside>
95125

96126
{/* Main content - Article */}
97-
<main className="flex-1 overflow-auto bg-[#010409]">
127+
<main ref={mainRef} className="flex-1 overflow-auto bg-[#010409]">
98128
<div className="max-w-3xl mx-auto px-16 py-20">
99129
<article className="space-y-6">
100130
{/* Introduction */}

0 commit comments

Comments
 (0)