Skip to content

Commit dfc9618

Browse files
authored
feat: use conversation list smooth (#2881)
1 parent 107ff7d commit dfc9618

File tree

11 files changed

+195
-346
lines changed

11 files changed

+195
-346
lines changed

apps/web/client/src/app/project/[id]/_components/right-panel/chat-tab/chat-messages/index.tsx

Lines changed: 19 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,18 @@ import type { EditMessage } from '@/app/project/[id]/_hooks/use-chat';
44
import { useEditorEngine } from '@/components/store/editor';
55
import { transKeys } from '@/i18n/keys';
66
import { type ChatMessage } from '@onlook/models/chat';
7-
import { ChatMessageList } from '@onlook/ui/chat/chat-message-list';
7+
import {
8+
Conversation,
9+
ConversationContent,
10+
ConversationScrollButton
11+
} from '@onlook/ui/ai-elements';
812
import { Icons } from '@onlook/ui/icons';
913
import { assertNever } from '@onlook/utility';
1014
import { observer } from 'mobx-react-lite';
1115
import { useTranslations } from 'next-intl';
12-
import { useCallback, useMemo } from 'react';
16+
import { useCallback } from 'react';
1317
import { AssistantMessage } from './assistant-message';
1418
import { ErrorMessage } from './error-message';
15-
import { StreamMessage } from './stream-message';
1619
import { UserMessage } from './user-message';
1720

1821
interface ChatMessagesProps {
@@ -23,28 +26,13 @@ interface ChatMessagesProps {
2326
}
2427

2528
export const ChatMessages = observer(({
26-
messages: baseMessages,
29+
messages,
2730
onEditMessage,
2831
isStreaming,
2932
error,
3033
}: ChatMessagesProps) => {
3134
const editorEngine = useEditorEngine();
3235
const t = useTranslations();
33-
const { messages, streamedMessage }: { messages: ChatMessage[], streamedMessage: ChatMessage | null } = useMemo(() => {
34-
if (isStreaming) {
35-
const lastAssistantMessage = baseMessages[baseMessages.length - 1];
36-
if (lastAssistantMessage && lastAssistantMessage.role === 'assistant') {
37-
return {
38-
messages: baseMessages.slice(0, -1),
39-
streamedMessage: lastAssistantMessage,
40-
};
41-
}
42-
}
43-
return {
44-
messages: baseMessages,
45-
streamedMessage: null,
46-
};
47-
}, [baseMessages, isStreaming]);
4836

4937
const renderMessage = useCallback(
5038
(message: ChatMessage, index: number) => {
@@ -68,7 +56,7 @@ export const ChatMessages = observer(({
6856
default:
6957
assertNever(message.role);
7058
}
71-
return <div key={`message-${message.id}-${index}`}>{messageNode}</div>;
59+
return <div key={`message-${message.id}-${index}`} className="my-2">{messageNode}</div>;
7260
},
7361
[onEditMessage],
7462
);
@@ -87,17 +75,17 @@ export const ChatMessages = observer(({
8775
}
8876

8977
return (
90-
<ChatMessageList
91-
contentKey={`${messages.map((m) => m.id).join('|')}${isStreaming ? `|${messages?.[messages.length - 1]?.id ?? ''}` : ''}`}
92-
>
93-
{messages.map((message, index) => renderMessage(message, index))}
94-
{streamedMessage && <StreamMessage message={streamedMessage} />}
95-
{error && <ErrorMessage error={error} />}
96-
{isStreaming && <div className="flex w-full h-full flex-row items-center gap-2 px-4 my-2 text-small content-start text-foreground-secondary">
97-
<Icons.LoadingSpinner className="animate-spin" />
98-
<p>Thinking ...</p>
99-
</div>}
100-
</ChatMessageList>
78+
<Conversation className="h-full w-full">
79+
<ConversationContent className="p-0 m-0">
80+
{messages.map((message, index) => renderMessage(message, index))}
81+
{error && <ErrorMessage error={error} />}
82+
{isStreaming && <div className="flex w-full h-full flex-row items-center gap-2 px-4 my-2 text-small content-start text-foreground-secondary">
83+
<Icons.LoadingSpinner className="animate-spin" />
84+
<p>Thinking ...</p>
85+
</div>}
86+
</ConversationContent>
87+
<ConversationScrollButton />
88+
</Conversation>
10189
);
10290
},
10391
);

apps/web/client/src/app/project/[id]/_components/right-panel/chat-tab/chat-messages/markdown-renderer.tsx

Lines changed: 0 additions & 46 deletions
This file was deleted.

apps/web/client/src/app/project/[id]/_components/right-panel/chat-tab/chat-messages/message-content/index.tsx

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import type { ChatMessage } from '@onlook/models';
2-
import { Reasoning, ReasoningContent, ReasoningTrigger } from '@onlook/ui/ai-elements';
2+
import { Reasoning, ReasoningContent, ReasoningTrigger, Response } from '@onlook/ui/ai-elements';
33
import { cn } from '@onlook/ui/utils';
44
import type { ToolUIPart } from 'ai';
55
import { observer } from 'mobx-react-lite';
6-
import { MarkdownRenderer } from '../markdown-renderer';
76
import { ToolCallDisplay } from './tool-call-display';
87

98
export const MessageContent = observer(
@@ -22,13 +21,10 @@ export const MessageContent = observer(
2221
const isLastPart = idx === parts.length - 1;
2322
if (part.type === 'text') {
2423
return (
25-
<MarkdownRenderer
26-
messageId={messageId}
27-
key={part.text}
28-
content={part.text}
29-
applied={applied}
30-
isStream={isStream}
31-
/>
24+
<Response key={part.text}>
25+
{part.text}
26+
</Response>
27+
3228
);
3329
} else if (part.type.startsWith('tool-')) {
3430
const toolPart = part as ToolUIPart;

apps/web/client/src/app/project/[id]/_components/right-panel/chat-tab/chat-messages/user-message.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,9 @@ export const UserMessage = ({ onEditMessage, message }: UserMessageProps) => {
8484
toast.promise(
8585
onEditMessage(message.id, getUserMessageContent(message), ChatType.EDIT),
8686
{
87-
loading: 'Resubmitting message...',
88-
success: 'Message resubmitted successfully',
8987
error: 'Failed to resubmit message',
9088
}
91-
)
89+
)
9290
};
9391

9492
const sendMessage = async (newContent: string) => {

0 commit comments

Comments
 (0)