| 1 | import { useLayoutEffect, useRef } from "react"; |
| 2 | |
| 3 | /** Keeps a running reasoning pane at its own tail until the reader scrolls up. */ |
| 4 | export function useReasoningScrollFollow( |
| 5 | content: string, |
| 6 | active: boolean, |
| 7 | ) { |
| 8 | const elementRef = useRef<HTMLDivElement>(null); |
| 9 | const followRef = useRef(true); |
| 10 | |
| 11 | const onScroll = () => { |
| 12 | const element = elementRef.current!; |
| 13 | followRef.current = element.scrollHeight - element.scrollTop - element.clientHeight <= 8; |
| 14 | }; |
| 15 | |
| 16 | useLayoutEffect(() => { |
| 17 | if (!active || !followRef.current) return; |
| 18 | const element = elementRef.current; |
| 19 | if (!element) return; |
| 20 | // This is the reasoning pane's own nested scroller, not the transcript. |
| 21 | element.scrollTop = element.scrollHeight; |
| 22 | }, [active, content]); |
| 23 | |
| 24 | return [elementRef, onScroll] as const; |
| 25 | } |
| 26 |