A full assistant chat workspace: history, threads with sources, and context.
Import it and pass your content. The props that matter most are listed next.
"use client";
import * as React from "react";
import { ChatApp, type ChatMessage } from "@/components/ui/notchset/blocks/chat-app";
const models = [{ id: "flash", name: "ATLAS 3 FLASH", label: "Atlas 3 Flash", price: "$0.0007 / RUN", quality: 0.6, speed: 0.85 }];
export function Assistant() {
const [messages, setMessages] = React.useState<ChatMessage[]>([]);
const [active, setActive] = React.useState<string | null>(null);
return (
<ChatApp
org="ACME LABS"
user={{ name: "Maya Kerr", initials: "MK" }}
threads={active ? [{ id: active, title: "New chat", group: "TODAY", time: "NOW", questions: 1 }] : []}
activeThreadId={active}
onNewChat={() => {
setActive(null);
setMessages([]);
}}
messages={messages}
models={models}
model="flash"
contextSources={[]}
context={[]}
suggestions={[{ kind: "EVALS", text: "Which suites got worse?", reads: "READS 1,200 CASES" }]}
onSend={({ text }) => {
// Post to your API here; stream the answer into the assistant message's paragraphs.
setActive("t1");
setMessages((m) => [...m, { id: String(m.length), role: "user", text }, { id: `${m.length}a`, role: "assistant", status: "checking", paragraphs: [] }]);
}}
/>
);
}org / user / logo–
string / { name, initials } / ReactNodeWhose workspace, who is asking, and the rail's mark.
threads–
{ id, title, group, time, questions }[]History, grouped by group in the order groups first appear. A thread that arrives after mount types its title in.
activeThreadId / onSelectThread / onNewChat–
string | nullnull shows the empty state.
messages–
({ id, role: 'user', text, context? } | { id, role: 'assistant', status, source?, paragraphs, table?, meta?, followUps? })[]The active thread. Grow paragraphs as an answer streams; status done reveals copy, meta and follow-ups.
models / model / onModelChange–
{ id, name, label, price, quality, speed }[]quality and speed are 0–1 for the meters.
contextSources / context / onContextChange–
{ id, label, detail }[] / string[]What the next message reads; chosen ones become chips in the composer.
suggestions–
{ kind, text, reads }[]The empty state's ledger; keys 1–4 pick the first four.
onSend–
({ text, model, context }) => voidCalled on send, a suggestion or a follow-up.
usage–
{ tokens, cost, limit, alertAt? }Today's spend in the aside; alertAt (0–1, default 0.8) is marked in signal.
eyebrow / headline / placeholder–
stringThe empty state's words and the composer's hint.
ChatAppdata-slot="chat-app"
The block: rail, history, thread, composer and aside.
components/ui/notchset/blocks/chat-app.tsx
This component is included with Pro.
Try the live preview above. Get Pro to install the source.
pnpm dlx shadcn@latest add @beautiful-ui-pro/chat-appNeeds your registry key. Your components.json style picks the Base UI or Radix build: radix-*, new-york and default get Radix, base-* gets Base UI.
The CLI adds the styles to the CSS file named in components.json (tailwind.css). Check that it points at your global stylesheet, that the project uses Tailwind CSS v4, and that the file is imported in your root layout. Installed by hand: paste styles.css into that file.
Give your coding assistant the Markdown guide instead of screenshots.
https://beautiful-ui.dev/api/mcp (setup)v1.0.0 · 2026-10-03
First release
Pro is in early access.