animui
ComponentsBlocksDocsPackageTry the demo
Introduction
Installation
Theming
Motion
AI guide
Changelog
Metrics dashboard
KPI drilldown
Metric explorer
Revenue explorer
MRR waterfall
Cohort retention
Usage forecast
Journey flow
Choropleth explorer
Connected scatter
Market terminal
Budget variance
Small multiples
Line replay
AI chat
AI composer
Agent run
AI side panel
SidebarPro4
Page header
Command palette
Notification center
Empty states
Search resultsPro
Login and sign up5
OTP input
Multi-step formPro
Settings page
Settings command
Security settings
Billing overview
Usage billing
Cancel flow
Team members
Invite people
Team directory
Roles and permissions
API keys
Webhooks
Integrations
Environment variables
Plan comparison
Pricing calculatorPro
Usage pricingPro
Cart drawerPro
Checkout summaryPro
Invoice studio
Wallet card
Product listing
Product detail
Inbox triage
Support conversation
Support widget
Help centerNew
File upload
Media playerPro
Week calendar
Availability picker
Project board
Release readiness
Kanban boardNew
Hero section
Hero signupPro
Scroll storyPro
Spotlight gridPro
Feature bentoPro
Comparison table
Logo marquee
Studio perspectivesPro
Stats band
Changelog feed
FAQ section
Contact section
Team showcasePro
Blog grid
Site header
Site footer
CTA section
Newsletter signup
Activity terrain
Revenue globe
Customer galaxy
Semantic zoom
Layout morph
What’s new8 new
BlocksAI chat

AI chatPro

A complete AI chat with streamed markdown answers, folding reasoning, tool chips, citations, and a model switcher.

Live block · sample data

When to use

  • A full page assistant with conversation history, model choice, and streamed answers.
  • Research or support assistants that show tool calls and cite sources inline.
  • Products that need regenerate, answer versions, and editable prompts out of the box.

When not to use

  • Use ai-composer when you only need the prompt input.
  • Use chat-thread for person to person messaging without model output.
  • Use support-widget for a small floating help chat.

Installation

Install animui once, then import any component or block from its typed package entry.

animui · 250 components and blocks

React 19 and React DOM 19 are required. The package includes Free and Pro entries, styles and TypeScript declarations.

npm install https://animui.stracture.net/__local/package.tgz

Load the stylesheet once at your app root, then use the typed component import:

import 'animui/styles.css';
import { AiChat } from 'animui/ai-chat';

Read the Code tab for the implementation files and the API reference below for required props.

Download animui 0.3.0 · Agent guide

Usage

Use this as a starting point and replace the sample data with your own.

example.tsx
1"use client";2 3import { AiChat } from "animui/ai-chat";4import type { ChatResponder } from "animui/ai-chat";5 6const respond: ChatResponder = async function* (request, signal) {7  const response = await fetch("/api/chat", {8    method: "POST",9    body: JSON.stringify({ messages: request.messages, model: request.model }),10    signal,11  });12  const reader = response.body!.pipeThrough(new TextDecoderStream()).getReader();13  while (true) {14    const { value, done } = await reader.read();15    if (done) break;16    yield { type: "text", text: value };17  }18};19 20export function Assistant() {21  return (22    <AiChat23      respond={respond}24      notice={null}25      models={[{ id: "default", name: "Default", description: "Balanced for everyday work" }]}26      defaultModel="default"27      defaultConversations={[]}28      user={{ name: "Ava Mitchell", detail: "Pro plan" }}29    />30  );31}
Built fromMotion

API reference

5 parts. The first is the root.

AiChat

A full AI chat surface: a collapsible conversation list, streamed markdown answers, a reasoning panel, tool call chips, citations with source cards, regenerate with versions, editable prompts, a model switcher, image attachments, and a send button that becomes stop. Connect respond to your model. Also the default export.

PropTypeDefaultDescription
defaultConversationsChatConversation[]sampleConversationsInitial conversations. The block owns them afterwards.
onConversationsChange(conversations: ChatConversation[]) => void–Called after every change, including each streamed chunk. Not called on mount.
activeIdstring | null–Controlled open conversation id; null shows a new chat.
defaultActiveIdstring | nullnullOpen conversation on mount when uncontrolled.
onActiveChange(id: string | null) => void–Called when a conversation is opened or a new chat starts.
modelsChatModel[]sampleModelsOptions in the model switcher.
modelstring–Controlled model id.
defaultModelstring"atlas"Starting model id when uncontrolled.
onModelChange(id: string) => void–Called when a model is chosen.
sidebarOpenboolean–Controlled sidebar state on wide layouts.
defaultSidebarOpenbooleantrueStarting sidebar state on wide layouts.
onSidebarOpenChange(open: boolean) => void–Called when the wide sidebar opens or closes.
suggestionsChatSuggestion[]sampleSuggestionsPrompts offered on an empty chat.
respondChatRespondersampleResponder(request, signal) => AsyncIterable<ChatStreamEvent>. Streams thinking, tool, sources, and text events. The default plays scripted samples.
greetingstring"What are we working on?"Heading on an empty chat.
noticeReactNode"Sample responses"Small note in the header. Pass null to hide it.
user{ name: string; avatar?: string; detail?: string }{ name: "Emma Collins", avatar: "/media/people/emma-collins.jpg", detail: "Team plan" }Account shown at the bottom of the sidebar.
classNamestring–Extra class on the root.

ChatResponder

Exported type. (request: ChatRequest, signal: AbortSignal) => AsyncIterable<ChatStreamEvent>. ChatRequest is { conversationId, messages, prompt, attachments, model }. Stop aborts the signal.

No props.

ChatStreamEvent

Exported type. { type: "thinking"; text } appends reasoning, { type: "tool"; tool } adds or updates a ChatToolCall by id, { type: "sources"; sources } replaces the citation list, { type: "text"; text } appends answer markdown. The first tool or text event closes the thinking panel.

No props.

sampleResponder

The default scripted responder, exported for demos and tests. It honors the abort signal.

No props.

StreamText

Exported from ai-chat/markdown.tsx. Plain streamed text, such as reasoning: the same per-word fade as answers, without markdown blocks. Newlines become line breaks. The same file exports Markdown, parseBlocks, plainText, and CopyControl.

PropTypeDefaultDescription
textRequiredstring–Text so far.
streamingRequiredboolean–Animates newly arrived words while true.
reducedRequiredboolean–Pass the reduced motion preference; true renders words without the fade.
classNamestring–Class on the paragraph.

Keyboard interactions

Enter
Sends the message. Shift Enter adds a new line; IME composition is respected.
Escape
Stops generation from the composer, cancels a prompt edit, closes a source card, or closes the narrow drawer.
Arrow Down
On the model pill, opens the model list.
Arrow UporDown, HomeorEnd, EnterorSpace
Move through and choose in the model list; Escape closes it and returns focus to the pill.
Tab to a citation
Keyboard focus opens the source card; Enter toggles it.

Accessibility

  • The sidebar is an aside labelled "Chat history" with a nav of conversations; the current one has aria-current="page".
  • Streaming answers set aria-busy. A polite live region announces generation, completion time, stops, and errors.
  • The model switcher is a button with aria-haspopup="listbox" and a listbox using aria-activedescendant.
  • Citation chips are labelled with source number, title, and domain; the source card is a role="dialog" linked with aria-controls.
  • Thinking, tool detail, and source list toggles use aria-expanded and aria-controls. Icon buttons all have labels.

Motion

  • Streamed words fade and unblur in with a CSS keyframe; code lines fade in as they arrive.
  • Answer height follows content on a spring through a ResizeObserver, so streaming grows instead of jumping.
  • The model pill grows into its menu as one surface and shrinks back around the new name.
  • Switching answer versions slides in the direction of travel. A new conversation title scrambles in.
  • The wide sidebar springs its width open and shut; on narrow layouts it slides over the thread as a drawer.
  • Reduced motion stops the word and line keyframes and spinners, removes offsets and blur, and uses short fades.

Responsive behavior

  • Below 720px root width the sidebar becomes a drawer over the thread with a scrim, closed by Escape or a tap outside.
  • The main column is a size container. At 560px and below the thread, dock, and header padding tighten; at 380px the header notice hides.
  • Message hover actions are always visible on devices without hover.

Performance

  • Every stream event patches state, so each chunk re-renders the active answer. Batch tiny tokens into larger chunks in respond.
  • A ResizeObserver keeps the thread pinned to the bottom while you are within 56px of it; scrolling up releases it and shows a jump button.
  • Messages are not virtualized. Very long conversations should load older messages on demand.

Notes for AI

Give your coding assistant the Markdown reference instead of screenshots.

  • Use for an assistant or copilot that streams answers, shows reasoning and tool use, and cites sources.
  • Write respond as an async generator that yields ChatStreamEvent objects and passes the signal to fetch. Write citations in the text as [1], [2], matching the sources event.
  • Conversations are uncontrolled after mount; persist them from onConversationsChange, ideally debounced since it fires per chunk.
  • Markdown supports headings, lists, quotes, tables, and fenced code with basic regex highlighting from markdown.tsx; swap in your own highlighter if you need more languages.
  • The reasoning panel renders with StreamText from markdown.tsx; reuse it for any plain streamed text next to the chat.
  • Attachments are images only, up to four, via picker, paste, or drop. They arrive as blob: URLs, so upload them inside respond if the model needs them.
/components/blocks/ai-chat/markdown

The full library index for assistants is at /llms.txt.

Related

AI composerProBlockA focused assistant thread where messages lift out of the composer and replies stream in.Chat threadComponentA chat thread with grouped messages, reactions, read receipts, typing, and a composer with attachments.Agent runProBlockA live AI agent run: steps stream in, tool calls expand, a diff waits for approval, and it all folds into a result.Support conversationProBlockA responsive message thread with useful quick replies and live feedback.Text shimmerComponentShow ongoing work with a calm light across the words.
PreviousPricing calculatorNextCheckout summary
animui · 84 block pagesllms.txt

On this page

  • Preview
  • When to use
  • When not to use
  • Installation
  • Usage
  • API reference
  • Keyboard
  • Accessibility
  • Motion
  • Responsive behavior
  • Performance
  • Notes for AI
  • Related
View as Markdown

Today

Previous 7 days

Emma CollinsTeam plan
Atlas 4

Model

  • Atlas 4 DeepThinks longer for analysis and code
  • Atlas 4Balanced for everyday work
  • Atlas 4 SwiftFastest answers, no reasoning
Sample responses

What are we working on?

Enter to send, Shift Enter for a new line