chat-02

PreviousNext

A chat in a sidebar.

Docs API Reference
simple-aiblock

Preview

Loading preview…
./src/registry/blocks/chat-02/components/app-sidebar.tsx
"use client";

import { useChat } from "@ai-sdk/react";
import { DefaultChatTransport, type UIMessage } from "ai";
import { MessageCircle, SquarePen } from "lucide-react";
import { Button } from "@/components/ui/button";
import {
	Sidebar,
	SidebarHeader,
	SidebarSeparator,
} from "@/components/ui/sidebar";
import {
	Tooltip,
	TooltipContent,
	TooltipProvider,
	TooltipTrigger,
} from "@/components/ui/tooltip";
import {
	ChatInput,
	ChatInputEditor,
	ChatInputGroupAddon,
	ChatInputSubmitButton,
	useChatInput,
} from "@/registry/ui/chat-input";
import {
	ChatMessage,
	ChatMessageAuthor,
	ChatMessageAvatar,
	ChatMessageAvatarAssistantIcon,
	ChatMessageAvatarUserIcon,
	ChatMessageContainer,
	ChatMessageContent,
	ChatMessageHeader,
	ChatMessageMarkdown,
	ChatMessageTimestamp,
} from "@/registry/ui/chat-message";
import {
	ChatMessageArea,
	ChatMessageAreaContent,
	ChatMessageAreaScrollButton,
} from "@/registry/ui/chat-message-area";

const INITIAL_MESSAGES: UIMessage[] = [
	{
		id: "1",
		parts: [
			{
				type: "text",
				text: "Hi! I'm here to help you build amazing user interfaces. What kind of app are you working on?",
			},
		],
		role: "assistant",
	},
	{
		id: "2",
		parts: [
			{
				type: "text",
				text: "I want to build a task management app but I'm not sure where to start with the UI design.",
			},
		],
		role: "user",
	},
	{
		id: "3",
		parts: [
			{
				type: "text",
				text: "That's a great project! Let's break it down. For a task management app, we should focus on three key components: a clean navigation sidebar, a main task list view, and an intuitive task creation interface. Would you like to start with the layout structure first?",
			},
		],
		role: "assistant",
	},
	{
		id: "4",
		parts: [
			{
				type: "text",
				text: "Yes, that sounds good! How should I organize the layout?",
			},
		],
		role: "user",
	},
	{
		id: "5",
		parts: [
			{
				type: "text",
				text: "For the layout, I recommend a two-column design. The left sidebar can contain project categories and filters, while the main area shows your tasks. This is a common pattern that users are familiar with. Should we start designing the sidebar first?",
			},
		],
		role: "assistant",
	},
];

export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
	const { messages, sendMessage, status, stop } = useChat({
		transport: new DefaultChatTransport({
			api: "/api/ai/chat",
		}),
		messages: INITIAL_MESSAGES,
	});
	const isLoading = status === "streaming" || status === "submitted";

	const { value, onChange, handleSubmit } = useChatInput({
		onSubmit: (parsedValue) => {
			sendMessage({
				role: "user",
				parts: [{ type: "text", text: parsedValue.content }],
			});
		},
	});

	return (
		<Sidebar {...props}>
			<SidebarHeader>
				<div className="flex items-center justify-between p-2">
					<div className="flex items-center gap-3">
						<div className="flex h-8 w-8 items-center justify-center rounded-lg bg-primary">
							<MessageCircle className="h-5 w-5 text-primary-foreground" />
						</div>
						<span className="text-lg font-semibold">simple-ai</span>
					</div>
					{/* New Chat Button */}
					<TooltipProvider>
						<Tooltip>
							<TooltipTrigger asChild>
								<Button size="icon" variant="ghost">
									<SquarePen className="h-5 w-5" />
									<span className="sr-only">New Chat</span>
								</Button>
							</TooltipTrigger>
							<TooltipContent>
								<p>New Chat</p>
							</TooltipContent>
						</Tooltip>
					</TooltipProvider>
				</div>
			</SidebarHeader>
			<SidebarSeparator />
			<div className="flex-1 flex flex-col h-full overflow-y-auto">
				<ChatMessageArea>
					<ChatMessageAreaContent>
						{messages.map((message) => {
							return (
								<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>
							);
						})}
					</ChatMessageAreaContent>
					<ChatMessageAreaScrollButton alignment="center" />
				</ChatMessageArea>
				<div className="p-4 max-w-2xl mx-auto w-full">
					<ChatInput
						value={value}
						onChange={onChange}
						onSubmit={handleSubmit}
						isStreaming={isLoading}
						onStop={stop}
					>
						<ChatInputEditor placeholder="Type a message..." />
						<ChatInputGroupAddon align="block-end">
							<ChatInputSubmitButton className="ml-auto" />
						</ChatInputGroupAddon>
					</ChatInput>
				</div>
			</div>
		</Sidebar>
	);
}

Installation

npx shadcn@latest add @simple-ai/chat-02

Usage

import { Chat02 } from "@/components/chat-02"
<Chat02 />