Skip to content

Commit 7345916

Browse files
authored
chore(compass-assistant): add auto-scroll to bottom with entry points and message sending COMPASS-9887 (#7374)
1 parent a266bdc commit 7345916

File tree

2 files changed

+34
-8
lines changed

2 files changed

+34
-8
lines changed

packages/compass-assistant/src/components/assistant-chat.spec.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -248,9 +248,8 @@ describe('AssistantChat', function () {
248248
userEvent.type(inputField, 'What is aggregation?');
249249
userEvent.click(sendButton);
250250

251-
expect(ensureOptInAndSendStub.called).to.be.true;
252-
253251
await waitFor(() => {
252+
expect(ensureOptInAndSendStub.called).to.be.true;
254253
expect(track).to.have.been.calledWith('Assistant Prompt Submitted', {
255254
user_input_length: 'What is aggregation?'.length,
256255
});
@@ -281,9 +280,8 @@ describe('AssistantChat', function () {
281280
userEvent.type(inputField, ' What is sharding? ');
282281
userEvent.click(screen.getByLabelText('Send message'));
283282

284-
expect(ensureOptInAndSendStub.called).to.be.true;
285-
286283
await waitFor(() => {
284+
expect(ensureOptInAndSendStub.called).to.be.true;
287285
expect(track).to.have.been.calledWith('Assistant Prompt Submitted', {
288286
user_input_length: 'What is sharding?'.length,
289287
});

packages/compass-assistant/src/components/assistant-chat.tsx

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useCallback, useEffect, useContext } from 'react';
1+
import React, { useCallback, useEffect, useContext, useRef } from 'react';
22
import type { AssistantMessage } from '../compass-assistant-provider';
33
import { AssistantActionsContext } from '../compass-assistant-provider';
44
import type { Chat } from '../@ai-sdk/react/chat-react';
@@ -211,6 +211,10 @@ export const AssistantChat: React.FunctionComponent<AssistantChatProps> = ({
211211
}) => {
212212
const track = useTelemetry();
213213
const darkMode = useDarkMode();
214+
const messagesContainerRef = useRef<HTMLDivElement>(null);
215+
const previousLastMessageId = useRef<string | undefined>(undefined);
216+
const { id: lastMessageId, role: lastMessageRole } =
217+
chat.messages[chat.messages.length - 1] ?? {};
214218

215219
const { ensureOptInAndSend } = useContext(AssistantActionsContext);
216220
const { messages, status, error, clearError, setMessages } = useChat({
@@ -222,6 +226,26 @@ export const AssistantChat: React.FunctionComponent<AssistantChatProps> = ({
222226
},
223227
});
224228

229+
const scrollToBottom = useCallback(() => {
230+
if (messagesContainerRef.current) {
231+
// Since the container uses flexDirection: 'column-reverse',
232+
// scrolling to the bottom means setting scrollTop to 0
233+
messagesContainerRef.current.scrollTop = 0;
234+
}
235+
}, []);
236+
237+
useEffect(() => {
238+
if (
239+
lastMessageId &&
240+
previousLastMessageId.current !== undefined &&
241+
lastMessageId !== previousLastMessageId.current &&
242+
lastMessageRole === 'user'
243+
) {
244+
scrollToBottom();
245+
}
246+
previousLastMessageId.current = lastMessageId;
247+
}, [lastMessageId, lastMessageRole, scrollToBottom]);
248+
225249
useEffect(() => {
226250
const hasExistingNonGenuineWarning = chat.messages.some(
227251
(message) => message.id === 'non-genuine-warning'
@@ -240,17 +264,18 @@ export const AssistantChat: React.FunctionComponent<AssistantChatProps> = ({
240264
}, [hasNonGenuineConnections, chat, setMessages]);
241265

242266
const handleMessageSend = useCallback(
243-
(messageBody: string) => {
267+
async (messageBody: string) => {
244268
const trimmedMessageBody = messageBody.trim();
245269
if (trimmedMessageBody) {
270+
await chat.stop();
246271
void ensureOptInAndSend?.({ text: trimmedMessageBody }, {}, () => {
247272
track('Assistant Prompt Submitted', {
248273
user_input_length: trimmedMessageBody.length,
249274
});
250275
});
251276
}
252277
},
253-
[track, ensureOptInAndSend]
278+
[track, ensureOptInAndSend, chat]
254279
);
255280

256281
const handleFeedback = useCallback(
@@ -351,6 +376,7 @@ export const AssistantChat: React.FunctionComponent<AssistantChatProps> = ({
351376
<div
352377
data-testid="assistant-chat-messages"
353378
className={messageFeedFixesStyles}
379+
ref={messagesContainerRef}
354380
>
355381
<div className={messagesWrapStyles}>
356382
{messages.map((message, index) => {
@@ -450,7 +476,9 @@ export const AssistantChat: React.FunctionComponent<AssistantChatProps> = ({
450476
<div className={inputBarStyleFixes}>
451477
<InputBar
452478
data-testid="assistant-chat-input"
453-
onMessageSend={handleMessageSend}
479+
onMessageSend={(messageBody) =>
480+
void handleMessageSend(messageBody)
481+
}
454482
state={status === 'submitted' ? 'loading' : undefined}
455483
textareaProps={{
456484
placeholder: 'Ask a question',

0 commit comments

Comments
 (0)