Substantial refinement/polish on content of webpage (not just structural/coding elements)
This commit is contained in:
@@ -1,21 +1,41 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
import { useState, useEffect, useCallback, useRef } from 'react'
|
||||
|
||||
const sectionTileMap: Record<string, string> = {
|
||||
'patient-summary': 'overview',
|
||||
'projects': 'projects',
|
||||
'section-experience': 'experience',
|
||||
'section-education': 'education',
|
||||
'section-skills': 'skills',
|
||||
}
|
||||
|
||||
const SCROLL_BOTTOM_THRESHOLD = 40
|
||||
|
||||
/**
|
||||
* Hook to track which section is currently visible using IntersectionObserver.
|
||||
* Observes tiles by their data-tile-id attribute inside main scroll content.
|
||||
* Includes a scroll-position safety net: when scrolled to the very top,
|
||||
* activates 'overview'; when scrolled to the very bottom, activates the
|
||||
* last mapped section ('skills').
|
||||
*
|
||||
* @returns The currently active section ID
|
||||
*/
|
||||
export function useActiveSection(): string {
|
||||
const [activeSection, setActiveSection] = useState<string>('overview')
|
||||
const scrollOverrideRef = useRef<string | null>(null)
|
||||
|
||||
const updateFromScroll = useCallback((root: HTMLElement) => {
|
||||
const { scrollTop, scrollHeight, clientHeight } = root
|
||||
const atBottom = scrollHeight - scrollTop - clientHeight <= SCROLL_BOTTOM_THRESHOLD
|
||||
const atTop = scrollTop <= SCROLL_BOTTOM_THRESHOLD
|
||||
|
||||
if (atTop) {
|
||||
scrollOverrideRef.current = 'overview'
|
||||
setActiveSection('overview')
|
||||
} else if (atBottom) {
|
||||
scrollOverrideRef.current = 'skills'
|
||||
setActiveSection('skills')
|
||||
} else {
|
||||
scrollOverrideRef.current = null
|
||||
}
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
const tiles = Array.from(
|
||||
@@ -27,6 +47,8 @@ export function useActiveSection(): string {
|
||||
|
||||
const observer = new IntersectionObserver(
|
||||
(entries) => {
|
||||
if (scrollOverrideRef.current) return
|
||||
|
||||
const visibleEntries = entries.filter((entry) => entry.isIntersecting)
|
||||
if (visibleEntries.length === 0) return
|
||||
|
||||
@@ -48,11 +70,16 @@ export function useActiveSection(): string {
|
||||
|
||||
tiles.forEach((tile) => observer.observe(tile))
|
||||
|
||||
const handleScroll = () => updateFromScroll(root)
|
||||
root.addEventListener('scroll', handleScroll, { passive: true })
|
||||
handleScroll()
|
||||
|
||||
return () => {
|
||||
tiles.forEach((tile) => observer.unobserve(tile))
|
||||
observer.disconnect()
|
||||
root.removeEventListener('scroll', handleScroll)
|
||||
}
|
||||
}, [])
|
||||
}, [updateFromScroll])
|
||||
|
||||
return activeSection
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user