Skip to content

Commit 07941ac

Browse files
authored
Merge branch 'master' into matomo-cleanup
2 parents 6d52aec + 82f619e commit 07941ac

File tree

1 file changed

+33
-6
lines changed

1 file changed

+33
-6
lines changed

libs/remix-ui/remix-ai-assistant/src/components/remix-ui-remix-ai-assistant.tsx

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ export const RemixUiRemixAiAssistant = React.forwardRef<
6464
const contextBtnRef = useRef(null)
6565
const textareaRef = useRef<HTMLTextAreaElement>(null)
6666
const aiChatRef = useRef<HTMLDivElement>(null)
67+
const userHasScrolledRef = useRef(false)
68+
const lastMessageCountRef = useRef(0)
6769

6870
useOnClickOutside([modelBtnRef, contextBtnRef], () => setShowAssistantOptions(false))
6971
useOnClickOutside([modelBtnRef, contextBtnRef], () => setShowContextOptions(false))
@@ -224,13 +226,25 @@ export const RemixUiRemixAiAssistant = React.forwardRef<
224226
props.onMessagesChange?.(messages)
225227
}, [messages, props.onMessagesChange])
226228

227-
// always scroll to bottom when messages change
229+
// Smart auto-scroll: only scroll to bottom if:
228230
useEffect(() => {
229231
const node = historyRef.current
230-
if (node && messages.length > 0) {
232+
if (!node || messages.length === 0) return
233+
234+
const isAtBottom = node.scrollHeight - node.scrollTop - node.clientHeight < 100
235+
const userSentNewMessage = messages.length > lastMessageCountRef.current &&
236+
messages[messages.length - 1]?.role === 'user'
237+
// Auto-scroll conditions:
238+
// - User sent a new message (always scroll)
239+
// - User hasn't manually scrolled up (userHasScrolledRef is false)
240+
// - Currently streaming and user is near bottom
241+
if (userSentNewMessage || !userHasScrolledRef.current || (isStreaming && isAtBottom)) {
231242
node.scrollTop = node.scrollHeight
243+
userHasScrolledRef.current = false
232244
}
233-
}, [messages])
245+
246+
lastMessageCountRef.current = messages.length
247+
}, [messages, isStreaming])
234248

235249
useEffect(() => {
236250
if (textareaRef.current) {
@@ -662,11 +676,24 @@ export const RemixUiRemixAiAssistant = React.forwardRef<
662676
)
663677
const chatHistoryRef = useRef<HTMLElement | null>(null)
664678

679+
// Detect manual user scrolling
665680
useEffect(() => {
666-
if (chatHistoryRef.current) {
667-
chatHistoryRef.current.scrollTop = chatHistoryRef.current.scrollHeight
681+
const node = historyRef.current
682+
if (!node) return
683+
684+
const handleScroll = () => {
685+
const isAtBottom = node.scrollHeight - node.scrollTop - node.clientHeight < 100
686+
687+
if (!isAtBottom) {
688+
userHasScrolledRef.current = true
689+
} else {
690+
userHasScrolledRef.current = false
691+
}
668692
}
669-
}, [messages])
693+
694+
node.addEventListener('scroll', handleScroll)
695+
return () => node.removeEventListener('scroll', handleScroll)
696+
}, [])
670697

671698
const maximizePanel = async () => {
672699
await props.plugin.call('layout', 'maximisePinnedPanel')

0 commit comments

Comments
 (0)