feat: Add useScrollAnchor hook for scrolling functionality
This commit is contained in:
parent
024d0506f3
commit
f12523d3f0
87
src/hooks/useScrollAnchor.tsx
Normal file
87
src/hooks/useScrollAnchor.tsx
Normal file
@ -0,0 +1,87 @@
|
||||
import { useCallback, useEffect, useRef, useState } from "react"
|
||||
|
||||
export const useScrollAnchor = () => {
|
||||
const messagesRef = useRef<HTMLDivElement>(null)
|
||||
const scrollRef = useRef<HTMLDivElement>(null)
|
||||
const visibilityRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
const [isAtBottom, setIsAtBottom] = useState(true)
|
||||
const [isVisible, setIsVisible] = useState(false)
|
||||
|
||||
const scrollToBottom = useCallback(() => {
|
||||
if (messagesRef.current) {
|
||||
messagesRef.current.scrollIntoView({
|
||||
block: "end",
|
||||
behavior: "smooth"
|
||||
})
|
||||
}
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
if (messagesRef.current) {
|
||||
if (isAtBottom && !isVisible) {
|
||||
messagesRef.current.scrollIntoView({
|
||||
block: "end"
|
||||
})
|
||||
}
|
||||
}
|
||||
}, [isAtBottom, isVisible])
|
||||
|
||||
useEffect(() => {
|
||||
const { current } = scrollRef
|
||||
|
||||
if (current) {
|
||||
const handleScroll = (event: Event) => {
|
||||
const target = event.target as HTMLDivElement
|
||||
const offset = 25
|
||||
const isAtBottom =
|
||||
target.scrollTop + target.clientHeight >= target.scrollHeight - offset
|
||||
console.log(target.scrollTop, target.clientHeight, target.scrollHeight)
|
||||
setIsAtBottom(isAtBottom)
|
||||
}
|
||||
|
||||
current.addEventListener("scroll", handleScroll, {
|
||||
passive: true
|
||||
})
|
||||
|
||||
return () => {
|
||||
current.removeEventListener("scroll", handleScroll)
|
||||
}
|
||||
}
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
if (visibilityRef.current) {
|
||||
let observer = new IntersectionObserver(
|
||||
(entries) => {
|
||||
entries.forEach((entry) => {
|
||||
console.log(entry.isIntersecting)
|
||||
if (entry.isIntersecting) {
|
||||
setIsVisible(true)
|
||||
} else {
|
||||
setIsVisible(false)
|
||||
}
|
||||
})
|
||||
},
|
||||
{
|
||||
rootMargin: "0px 0px -100px 0px"
|
||||
}
|
||||
)
|
||||
|
||||
observer.observe(visibilityRef.current)
|
||||
|
||||
return () => {
|
||||
observer.disconnect()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
messagesRef,
|
||||
scrollRef,
|
||||
visibilityRef,
|
||||
scrollToBottom,
|
||||
isAtBottom,
|
||||
isVisible
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user