P
Pedro6:52 PM
Can you implement the new user authentication feature?
P
Project Assistant6:52 PM
Sure, I'll work on implementing the user authentication feature. I'll respond on the thread with updates as I progress.
P
Pedro6:52 PM
What's the progress on the other task?
"use client";
import type { UIMessage } from "@ai-sdk/react";
import { Copy, ThumbsUp } from "lucide-react";
import {
ChatMessage,
ChatMessageAction,
ChatMessageActions,
ChatMessageAuthor,
ChatMessageAvatar,
ChatMessageAvatarFallback,
ChatMessageAvatarImage,
ChatMessageContainer,
ChatMessageContent,
ChatMessageHeader,
ChatMessageMarkdown,
ChatMessageThread,
ChatMessageThreadAction,
ChatMessageThreadReplyCount,
ChatMessageThreadTimestamp,
ChatMessageTimestamp,
} from "@/components/ui/chat-message";
const messages: UIMessage<{
member: {
image: string;
name: string;
};
threadData?: {
messageCount: number;
lastReply: Date;
member: {
image: string;
name: string;
};
};
}>[] = [
{
id: "1",
parts: [
{
type: "text",
text: "Can you implement the new user authentication feature?",
},
],
role: "user",
metadata: {
member: {
image: "/avatar-1.png",
name: "Pedro",
},
},
},
{
id: "2",
parts: [
{
type: "text",
text: "Sure, I'll work on implementing the user authentication feature. I'll respond on the thread with updates as I progress.",
},
],
role: "assistant",
metadata: {
member: {
image: "/avatar-2.png",
name: "Project Assistant",
},
threadData: {
messageCount: 3,
lastReply: new Date(),
member: {
image: "/avatar-1.png",
name: "Pedro",
},
},
},
},
{
id: "3",
parts: [
{
type: "text",
text: "What's the progress on the other task?",
},
],
role: "user",
metadata: {
member: {
image: "/avatar-1.png",
name: "Pedro",
},
},
},
];
export function ChatMessageDemo() {
return (
<div className="w-full max-h-[400px] overflow-y-auto">
{messages.map((message) => (
<ChatMessage key={message.id}>
<ChatMessageActions>
<ChatMessageAction label="Copy">
<Copy className="size-4" />
</ChatMessageAction>
<ChatMessageAction label="Like">
<ThumbsUp className="size-4" />
</ChatMessageAction>
</ChatMessageActions>
<ChatMessageAvatar>
<ChatMessageAvatarImage
src={message.metadata?.member.image}
/>
<ChatMessageAvatarFallback>
{message.metadata?.member.name
.charAt(0)
.toUpperCase()}
</ChatMessageAvatarFallback>
</ChatMessageAvatar>
<ChatMessageContainer>
<ChatMessageHeader>
<ChatMessageAuthor>
{message.metadata?.member.name}
</ChatMessageAuthor>
<ChatMessageTimestamp createdAt={new Date()} />
</ChatMessageHeader>
<ChatMessageContent>
{message.parts
.filter((part) => part.type === "text")
.map((part) => (
<ChatMessageMarkdown
key={part.type}
content={part.text}
/>
))}
</ChatMessageContent>
{message.metadata?.threadData && (
<ChatMessageThread>
<ChatMessageAvatar>
<ChatMessageAvatarImage
src={
message.metadata?.threadData.member
.image
}
/>
<ChatMessageAvatarFallback>
{message.metadata?.threadData.member.name
.charAt(0)
.toUpperCase()}
</ChatMessageAvatarFallback>
</ChatMessageAvatar>
<ChatMessageThreadReplyCount>
{message.metadata.threadData.messageCount}{" "}
replies
</ChatMessageThreadReplyCount>
<ChatMessageThreadTimestamp
date={message.metadata.threadData.lastReply}
/>
<ChatMessageThreadAction />
</ChatMessageThread>
)}
</ChatMessageContainer>
</ChatMessage>
))}
</div>
);
}
Installation
pnpm dlx shadcn@latest add @simple-ai/chat-message
Examples
Simple Message
A minimal chat message without any actions or threading.
You6:52 PM
Hey, how are you doing today?
Assistant6:52 PM
I'm doing great! Just working on some projects. How can I help you?
You6:52 PM
I need help with my React application.
"use client";
import type { UIMessage } from "@ai-sdk/react";
import {
ChatMessage,
ChatMessageAuthor,
ChatMessageAvatar,
ChatMessageAvatarAssistantIcon,
ChatMessageAvatarUserIcon,
ChatMessageContainer,
ChatMessageContent,
ChatMessageHeader,
ChatMessageMarkdown,
ChatMessageTimestamp,
} from "@/components/ui/chat-message";
const messages: UIMessage[] = [
{
id: "1",
parts: [
{
type: "text",
text: "Hey, how are you doing today?",
},
],
role: "user",
},
{
id: "2",
parts: [
{
type: "text",
text: "I'm doing great! Just working on some projects. How can I help you?",
},
],
role: "assistant",
},
{
id: "3",
parts: [
{
type: "text",
text: "I need help with my React application.",
},
],
role: "user",
},
];
export function ChatMessageDemoSimple() {
return (
<div className="w-full max-h-[400px] overflow-y-auto">
{messages.map((message) => (
<ChatMessage key={message.id}>
<ChatMessageAvatar>
{message.role === "user" ? (
<ChatMessageAvatarUserIcon />
) : (
<ChatMessageAvatarAssistantIcon />
)}
</ChatMessageAvatar>
<ChatMessageContainer>
<ChatMessageHeader>
<ChatMessageAuthor>
{message.role === "user" ? "You" : "Assistant"}
</ChatMessageAuthor>
<ChatMessageTimestamp createdAt={new Date()} />
</ChatMessageHeader>
<ChatMessageContent>
{message.parts
.filter((part) => part.type === "text")
.map((part) => (
<ChatMessageMarkdown
key={part.type}
content={part.text}
/>
))}
</ChatMessageContent>
</ChatMessageContainer>
</ChatMessage>
))}
</div>
);
}
With Avatar Images
Chat messages using image avatars instead of icons.
You6:52 PM
Hi there! This is a user message with an avatar image.
Assistant6:52 PM
And this is an assistant message with its own avatar image.
You6:52 PM
Great! Avatar images are displaying properly.
"use client";
import type { UIMessage } from "@ai-sdk/react";
import {
ChatMessage,
ChatMessageAuthor,
ChatMessageAvatar,
ChatMessageAvatarImage,
ChatMessageContainer,
ChatMessageContent,
ChatMessageHeader,
ChatMessageMarkdown,
ChatMessageTimestamp,
} from "@/components/ui/chat-message";
const messages: UIMessage<{
avatarImage: string;
}>[] = [
{
id: "1",
parts: [
{
type: "text",
text: "Hi there! This is a user message with an avatar image.",
},
],
role: "user",
metadata: {
avatarImage: "/avatar-1.png",
},
},
{
id: "2",
parts: [
{
type: "text",
text: "And this is an assistant message with its own avatar image.",
},
],
role: "assistant",
metadata: {
avatarImage: "/avatar-2.png",
},
},
{
id: "3",
parts: [
{
type: "text",
text: "Great! Avatar images are displaying properly.",
},
],
role: "user",
metadata: {
avatarImage: "/avatar-1.png",
},
},
];
export function ChatMessageDemoAvatarImage() {
return (
<div className="w-full max-h-[400px] overflow-y-auto">
{messages.map((message) => (
<ChatMessage key={message.id}>
<ChatMessageAvatar>
<ChatMessageAvatarImage
src={message.metadata?.avatarImage}
alt="Avatar"
/>
</ChatMessageAvatar>
<ChatMessageContainer>
<ChatMessageHeader>
<ChatMessageAuthor>
{message.role === "user" ? "You" : "Assistant"}
</ChatMessageAuthor>
<ChatMessageTimestamp createdAt={new Date()} />
</ChatMessageHeader>
<ChatMessageContent>
{message.parts
.filter((part) => part.type === "text")
.map((part) => (
<ChatMessageMarkdown
key={part.type}
content={part.text}
/>
))}
</ChatMessageContent>
</ChatMessageContainer>
</ChatMessage>
))}
</div>
);
}