feat(SW-1960): Improved scrolling and tabnavigation on hotel pages

Approved-by: Matilda Landström
This commit is contained in:
Erik Tiekstra
2025-05-26 12:32:18 +00:00
parent a8e52c6c8a
commit d73f8d844e
8 changed files with 205 additions and 69 deletions

View File

@@ -1,5 +1,7 @@
import { useCallback, useEffect, useMemo, useRef, useState } from "react"
import { debounce } from "../utils/debounce"
export default function useScrollSpy(
sectionIds: string[],
options: IntersectionObserverInit = {}
@@ -9,6 +11,7 @@ export default function useScrollSpy(
} {
const [activeSectionId, setActiveSectionId] = useState("")
const observerIsInactive = useRef(false)
const safetyTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null)
const mergedOptions = useMemo(
() => ({
@@ -42,6 +45,22 @@ export default function useScrollSpy(
[]
)
// Scroll event listener to reset the observerIsInactive state
// This is to support the pauseScrollSpy function to prevent the observer from firing when scrolling.
useEffect(() => {
const handleScroll = debounce(() => {
if (observerIsInactive.current) {
observerIsInactive.current = false
}
}, 200)
window.addEventListener("scroll", handleScroll, { passive: true })
return () => {
window.removeEventListener("scroll", handleScroll)
}
}, [])
useEffect(() => {
const observer = new IntersectionObserver(handleIntersection, mergedOptions)
const elements = sectionIds
@@ -55,12 +74,18 @@ export default function useScrollSpy(
return () => elements.forEach((el) => el && observer.unobserve(el))
}, [sectionIds, mergedOptions, handleIntersection])
const pauseScrollSpy = () => {
function pauseScrollSpy() {
observerIsInactive.current = true
setTimeout(() => {
if (safetyTimeoutRef.current) {
clearTimeout(safetyTimeoutRef.current)
}
// Safety timeout - maximum time to wait before re-enabling
safetyTimeoutRef.current = setTimeout(() => {
observerIsInactive.current = false
}, 500)
safetyTimeoutRef.current = null
}, 1500)
}
return { activeSectionId, pauseScrollSpy }