feat: sticky list mode switcher

This commit is contained in:
codytseng
2025-01-24 16:53:01 +08:00
parent ee21e19625
commit 1df975dfc6
7 changed files with 175 additions and 183 deletions

View File

@@ -0,0 +1,80 @@
import { createContext, useContext, useEffect, useState } from 'react'
type TDeepBrowsingContext = {
deepBrowsing: boolean
lastScrollTop: number
}
const DeepBrowsingContext = createContext<TDeepBrowsingContext | undefined>(undefined)
export const useDeepBrowsing = () => {
const context = useContext(DeepBrowsingContext)
if (!context) {
throw new Error('useDeepBrowsing must be used within a DeepBrowsingProvider')
}
return context
}
export function DeepBrowsingProvider({
children,
active,
scrollAreaRef
}: {
children: React.ReactNode
active: boolean
scrollAreaRef?: React.RefObject<HTMLDivElement>
}) {
const [deepBrowsing, setDeepBrowsing] = useState(false)
const [lastScrollTop, setLastScrollTop] = useState(0)
useEffect(() => {
if (!active) return
const handleScroll = () => {
const atBottom = !scrollAreaRef
? window.innerHeight + window.scrollY >= document.body.offsetHeight - 20
: scrollAreaRef.current
? scrollAreaRef.current?.clientHeight + scrollAreaRef.current?.scrollTop >=
scrollAreaRef.current?.scrollHeight - 20
: false
if (atBottom) {
setDeepBrowsing(false)
return
}
const scrollTop = (!scrollAreaRef ? window.scrollY : scrollAreaRef.current?.scrollTop) || 0
const diff = scrollTop - lastScrollTop
if (scrollTop <= 800) {
setDeepBrowsing(false)
setLastScrollTop(scrollTop)
return
}
if (diff > 20) {
setDeepBrowsing(true)
setLastScrollTop(scrollTop)
} else if (diff < -20) {
setDeepBrowsing(false)
setLastScrollTop(scrollTop)
}
}
if (!scrollAreaRef) {
window.addEventListener('scroll', handleScroll)
return () => {
window.removeEventListener('scroll', handleScroll)
}
}
scrollAreaRef.current?.addEventListener('scroll', handleScroll)
return () => {
scrollAreaRef.current?.removeEventListener('scroll', handleScroll)
}
}, [lastScrollTop, active])
return (
<DeepBrowsingContext.Provider value={{ deepBrowsing, lastScrollTop }}>
{children}
</DeepBrowsingContext.Provider>
)
}