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