Skip to content
WingoUI
ComponentsTemplatesDocsPricingAI agentsBlogChangelogContact
Components
Buttons & Actions
ButtonButton GroupCopy ButtonDelete ButtonTheme ToggleToggleToggle Group
Inputs
Avatar UploadCalendarCheckboxColor PickerComboboxCountry SelectCron PickerCurrency InputDate PickerDate Range PickerDate Time PickerDuration PickerEmail InputEmoji PickerFile UploadFilter BuilderInputInput GroupListboxMasked InputMention InputMonth PickerMulti SelectNumber InputOTP InputPassword InputPhone InputRadio GroupRatingSearch InputSegmented ControlSelectSignature PadSliderSwitchTag InputTextareaTime PickerTimezone SelectTree Select
Forms
Address InputBooking WidgetCSV ImportFieldForm WizardInline EditInvoice line itemsRich Text EditorSchema Builder
Navigation
Back To TopBounce SidebarBreadcrumbCommand MenuGlobal SearchGooey NavHook SidebarNav MenuNav TabsPaginationProximity SidebarScroll ProgressSidebarStepsTable Of ContentsTabsTopbarUser MenuWorkspace Switcher
Overlays
Alert DialogContext MenuDialogDrawerDropdown MenuFamily DrawerHover CardPopoverShare DialogSheetShortcuts DialogTooltipTour
Feedback
AlertBannerCookie ConsentEmoji ReactionEmpty StateNotification BellNotification CenterProgressRoute ProgressSetup ChecklistSkeletonSpinnerToast
Data Display
Approval FlowAvatarBadgeCalendar ViewCode BlockComment ThreadContact cardCountdownDescription ListDiff ViewerFile ListFile managerFolderGanttJSON ViewerKbdLog ViewerMarkdownPresenceSchedulerTagTimelineTree View
Tables & Lists
Audit LogData TableDeal PipelineEditable GridKanbanListMembers tablePermissions MatrixTableTask ListVirtual List
Charts & Stats
Animated CounterArea chartBar chartDonut chartFunnel chartGaugeGitHub ActivityHeatmap calendarLeaderboardLine chartRadar chartRadial barSparklineStat CardTrackerTrend badge
Layout
AccordionApp ShellCardCollapsibleDetail LayoutEntity HeaderPage HeaderScroll AreaSeparatorSettings LayoutSplit ViewToolbar
Media
Audio PlayerCarouselCSV ViewerDOCX EditorDOCX ViewerExcel ViewerFile SystemImage compareImage CropperImage GalleryImage LightboxLocation MapPDF ViewerPowerPoint ViewerQR CodeStep PlayerVideo Player
AI Kit
Agent Status CardChat MessageChat ThreadChat WidgetConversation ListFluid OrbGrid RevealMatrix OrbModel PickerPrompt InputReasoning IndicatorRule BuilderSuggestion ChipsTool Call TimelineUsage MeterVoice InputWorkflow Canvas
Text & Effects
Background PatternGravity LettersMarqueeTerminalText AnimateText Rotate
Mobile
Action SheetBottom Tab BarFABHaptic ButtonHero HeaderInstall PromptLarge Title HeaderNotification BannerOnboarding CarouselPicker WheelPull To RefreshSlide To ConfirmSticky CTA BarSwipe DeckSwipeable Tabs
Commerce
Cart drawerCategory pickerCheckout stepsCoupon inputFavorite buttonFilter panelListing cardListing gridOrder trackerPricePrice rangePricing tableProduct galleryQuantity stepperReviewsSeller card
Marketing Sections
App Download SectionBlog Cards SectionCTA SectionFAQ SectionFeature GridFeature ShowcaseHero SectionIntegrations SectionLogo CloudMarketing FooterMarketing HeaderMarketing SectionNewsletter SectionPricing SectionStats SectionSteps SectionTeam SectionTestimonials SectionTimeline SectionVideo Section
Blocks
Admin Dashboard PageAdmin ShellAI Chat PageAPI Keys PageAutomation Builder PageCheckout PageCRM Contact PageCRM Pipeline PageError PagesInbox PageInvoice PageKPI DashboardListing Detail PageLogin PageMarketplace Home PageMarketplace Search PageMarketplace ShellMobile App HomeOnboarding FlowOrder History PagePost Listing WizardPricing PageProfile PageRegister PageSettings PageUsers Admin Page
Templates
About PageAcademy PageAccessibility PageAffiliate PageAgency PageAI Product PageAppointment Booking PageBlog PageBlog Post PageBug Bounty PageCareers PageChangelog PageCommunity PageCompare PageContact PageCustomer Story PageCustomers PageDemo Booking PageDevelopers PageDocs Home PageDownload PageEnterprise PageEvents PageExperts PageFAQ PageFeature PageGlossary PageHelp Article PageHelp Center PageHome Services PageImpact PageIntegration Detail PageIntegrations PageJob Detail PageLanding PageLaunch PageLegal PageManifesto PagePortfolio PagePress PageProduct Tour PagePromo PageReal Estate PageReferral PageResearch Report PageRestaurant PageRoadmap PageROI Calculator PageSecurity PageSolutions PageStartups PageStatus PageStorefront PageSwitch PageTemplate Gallery PageTravel PageWaitlist PageYear in Review Page
Hooks & Utilities
AI ChatChart kitCommerceDate utilsFile exportFile typesFiltersForm validationHapticsInvoicingMotion presetsNavigationNumber formatRelative timeRomanian locationsSpreadsheetText matchTonesUIProvideruseClipboarduseConsentuseControllableStateuseCooldownuseDebounceuseKeyboardInsetuseLocaleuseLongPressuseMediaControlsuseMediaQueryuseOverflowItemsusePersistedStateuseScrollEdgesuseScrollStateuseSelectionuseShortcutuseStickToBottom
GalleryTheme

Blocks

AI Chat Page

Blocks

AI Chat Page React block for Tailwind CSS v4

Admin ShellAPI Keys Page
Live props
State
defaultConversationId
defaultModel
loading
Behavior
initialPrompt
newChatShortcut
searchShortcut
locale
animateIn
Layout
height
sidebar
Appearance
variant
showUsage
tone
Content
assistantName
Code
import { AiChatPage } from "@/components/blocks/ai-chat-page"

<AiChatPage />
  1. Home
  2. Components
  3. Blocks
  4. AI Chat Page
Pro

AI Chat Page React block for Tailwind CSS v4

v1.0.1·Updated in 1.7.0

A React AI chat page with conversation history, a streaming thread with reasoning and tool calls, a prompt composer and plan usage.

The history sits on the left from 1024px (a left drawer behind the menu button below, from 768px with sidebar="open"): New chat (or ⇧⌘O) opens the greeting with six starter cards, the search filters titles, rows group into Pinned, Today, Yesterday and older, and each row's ⋯ menu renames (also F2 or a double click), pins, archives or deletes it after a confirmation. The panel button in the header slides the history away on desktop and the thread glides into the space. Click the title to rename the conversation inline (Enter saves, Escape cancels, an empty title keeps the old one). The model picker sits in the header's center on desktop and inside the composer on phones. Share copies a link with a toast; ⋯ renames, pins, shares, exports the conversation as a Markdown file and deletes it with an Undo toast. Type in the composer and press Enter to send (Shift+Enter for a new line), attach files with + or by dropping them, toggle Web search, Extended thinking and CRM data. The answer arrives as typing dots, then reasoning (Summit Pro or extended thinking), the CRM tool calls one by one and the streamed markdown; Stop or Escape keeps what arrived. Scroll up while it streams and the thread lets go, with a jump button to come back. Under the answer: follow-up rows, copy, regenerate and thumbs; edit a question to ask again. A prompt with the word "error" fails and shows Retry. Switching conversations stops a running answer. The sidebar footer shows the person, the plan and its reset date, a usage ring that opens the four meters and the Upgrade to Business link.

AI Chat Page is a Pro React block in the React blocks category, written in TypeScript for React 19 and Tailwind CSS v4. It installs as source with npx wingo-ui@latest add ai-chat-page, together with Avatar, Button, Chat Message, Chat Thread, Conversation List and 22 more and the npm packages motion and lucide-react.

Add to a project

Requirements: React 19 and Tailwind CSS v4, in Next.js (App Router or Pages), Vite or React Router. Installation guide · Next.js setup · Vite setup

npx wingo-ui@latest add ai-chat-page

AI Chat Page is part of Pro, with 298 more Pro items: $8 a month or $150 once. 14-day refund before you download any Pro item. See plans

Usage

Import AiChatPage from @/components/blocks/ai-chat-page.

// app/assistant/page.tsx: a standalone app screen (or inside the admin shell with height="fill")
"use client"

import { AiChatPage, type AiChatSendHandler } from "@/components/blocks/ai-chat-page"

// stream the answer from your own route (server-sent text chunks)
const onSend: AiChatSendHandler = async function* (message, { conversationId, model, tools, signal }) {
  const response = await fetch("/api/assistant", {
    method: "POST",
    body: JSON.stringify({ conversationId, model, tools, text: message.text }),
    signal,
  })
  const reader = response.body!.pipeThrough(new TextDecoderStream()).getReader()
  while (true) {
    const { value, done } = await reader.read()
    if (done) break
    yield value
  }
}

export default function AssistantPage() {
  return <AiChatPage onSend={onSend} defaultConversationId={null} />
}

Props

  • conversations
    AiConversation[]

    The history, controlled: ConversationItem (id, title, updatedAt, pinned, unread, archived, model) plus messages: ChatMessageData[] and optional followUps. Pair it with onConversationsChange, which also fires for every streamed chunk.

  • defaultConversations
    AiConversation[]

    The history while uncontrolled; defaults to AI_CHAT_SAMPLE.conversations (ten sample conversations, "Overdue invoices in September" with its reasoning, tool calls, table and email).

  • onConversationsChange
    (conversations: AiConversation[]) => void

    Called with the whole history after every change: a new chat, a message, a streamed chunk, a rename, a pin, an archive or a delete.

  • conversationId
    string | null

    The open conversation, controlled; null is a new chat.

  • defaultConversationIddefault "overdue-invoices"
    string | null

    The conversation open first; null ("new" in the playground) starts on the greeting.

  • onConversationChange
    (id: string | null) => void

    Called when a row, New chat, a delete or a first message changes the open conversation.

  • models
    AiModel[]

    The models of the pickers; defaults to AI_CHAT_SAMPLE.models (Summit Swift, Standard, Pro, Vision, Ultra locked to Business, Local 8B).

  • model
    string

    The chosen model's id, controlled; pair it with onModelChange.

  • defaultModeldefault "standard"
    string

    The model while uncontrolled. Summit Pro answers with a reasoning block first.

  • onModelChange
    (model: string) => void

    Called when the header or composer picker picks a model.

  • tools
    PromptTool[]

    The composer's toggles; defaults to AI_CHAT_SAMPLE.tools (Web search, Extended thinking, CRM data). The mock runs its CRM tool calls only with crm on and thinks first with reasoning on.

  • defaultActiveToolsdefault "["crm"]"
    string[]

    The tools switched on at first.

  • suggestions
    ChatSuggestion[]

    The starter cards of a new chat (two columns from 640px, one below); defaults to AI_CHAT_SAMPLE.suggestions, six sample starters.

  • usage
    UsageMeterItem[]

    The plan's meters behind the sidebar's usage ring; defaults to AI_CHAT_SAMPLE.usage (tokens, Pro messages, images, API cost). [] hides the ring.

  • plan
    AiChatPlan | null

    { name, resetsAt, upgrade: { label, description, href } } for the footer line "Pro · resets on Oct 1, 2026" and the upsell link; defaults to AI_CHAT_SAMPLE.plan, null hides both.

  • user
    ChatPerson

    The signed-in person ({ id, name, avatar }): the greeting's first name, the questions' author and the footer; defaults to Anna Price.

  • onSend
    (message: PromptInputMessage, context: AiChatSendContext) => (AsyncIterable<string> | Promise<string>)

    AiChatSendHandler; the context is { conversationId, model, tools, signal, messages }. Plug a real model here: yield text deltas to stream the answer or resolve with the whole of it; a rejection shows the message's error with Retry. The signal aborts on Stop, on switching conversations and on unmount. Without it a scripted mock streams (reasoning for Summit Pro, CRM tool calls, the canned answers of AI_CHAT_SAMPLE.replies, a generic answer otherwise; a prompt with the word "error" fails).

  • replies
    AiChatCannedReply[]

    The mock model's scripts ({ id, match: RegExp, reasoning?, toolCalls?, content, followUps? }), tested against the prompt folded to lowercase without diacritics; defaults to AI_CHAT_SAMPLE.replies.

  • initialPromptdefault ""
    string

    Sent once, shortly after mount, into the open conversation (a new one when none is open), like a ?q= deep link.

  • getShareUrl
    (conversation: AiConversation) => string

    The link Share copies; defaults to origin + /assistant/<id>.

  • sidebarFooter
    ReactNode

    Content under the usage block, in the sidebar and the drawer (a version line, help links).

  • heightdefault "screen"
    "fill" | "screen"

    screen is a standalone h-dvh app with its own <main>; fill takes what is left of a shell with layout="fill" (admin-shell) and scrolls inside its panes.

  • sidebardefault "auto"
    "auto" | "open" | "closed"

    auto: the history is open from 1024px and a left drawer below; open: inline from 768px (tablets too); closed: starts collapsed on desktop, the header button slides it in.

  • variantdefault "default"
    "default" | "bubbles" | "flat"

    The messages' layout, passed to ChatThread: the question in a bubble and the answer as text, both in bubbles, or both on the left with names.

  • newChatShortcutdefault "shift+mod+o"
    string

    Opens a new chat from anywhere, shown in the New chat tooltip; "" binds nothing.

  • searchShortcutdefault ""
    string

    Focuses the history search from anywhere ("mod+k"); "" binds nothing.

  • showUsagedefault true
    boolean

    The sidebar footer: the person, the plan line, the usage ring and the upsell.

  • assistantNamedefault "Summit Assistant"
    string

    The assistant's name in the sidebar brand, the composer placeholder, the message headers (flat) and screen reader text.

  • labels
    Partial<AiChatPageLabels>

    Every visible string, English by default (DEFAULT_AI_CHAT_PAGE_LABELS; AI_CHAT_PAGE_LABELS_EN is the same set). Nested keys (list, thread, message, markdown, reasoning, toolCalls, composer, modelPicker, usageMeter, suggestionChips, inlineEdit) translate the composed items.

  • localedefault "en-US"
    string

    Intl locale for dates, times, token counts and money.

  • now
    Date | number

    The reference time for the history groups and day separators; new messages move on from it. Defaults to the live clock.

  • tonedefault "neutral"
    "neutral" | "brand" | "success" | "warning" | "danger" | "info"

    The accent of the send button, the question bubbles, the selected row, the starter card icons and the brand mark.

  • loadingdefault false
    boolean

    The history, the title and the thread as skeletons; the composer is disabled.

  • animateIndefault true
    boolean

    The thread rises in once when the page mounts in the browser; off in thumbnails and under reduced motion.

  • linkComponentdefault "<a>"
    (props: LinkComponentProps) => ReactNode

    The router link for the upsell link; defaults to the LinkProvider's (a plain anchor).

  • className
    string

    Classes for the root.

  • classNames
    Partial<Record<AiChatPageSlot, string>>

    Classes for the parts: sidebar, brand, list, usage, main, header, title, thread, empty, drawer.

Parts

  • DEFAULT_AI_CHAT_PAGE_LABELS

    constant

    The English strings for every visible label, the default of labels. Type: AiChatPageLabels.

  • AI_CHAT_PAGE_LABELS_EN

    constant

    The same English strings under their older name, kept for existing imports.

  • AI_CHAT_SAMPLE

    constant

    The demo data: user, models, tools, suggestions, usage, plan, ten conversations, the mock replies and their defaults.

  • AI_CHAT_CONVERSATION_IDS

    constant

    The ids of the sample conversations, for a playground select or a deep link.

  • AI_CHAT_NOW

    constant

    The demo clock (Sep 24, 2026, 4:40 PM) as a timestamp, passed as now so history groups stay stable.

  • findCannedReply

    function

    The mock model's matcher: (prompt, replies?) => AiChatCannedReply, the first reply whose match fits the folded prompt, else a generic one.

  • AiChatPageProps

    type

    Props of AiChatPage, including the div attributes of the root.

  • AiChatSendHandler

    type

    The onSend signature: (message, context) => AsyncIterable<string> | Promise<string>.

  • AiConversation

    type

    A history entry: ConversationItem plus messages and optional followUps.

Examples

Open

New chat

The greeting and six starter cards; pick one and it streams.

Open

Streaming

Summit Pro thinks, then writes a plan with a table and code. Scroll up: it lets go.

Open

Inside admin-shell

height="fill" in the shell's fill layout at /assistant.

Open

Bubbles

variant="bubbles": both sides in bubbles.

Open

Renamed assistant, en-GB

assistantName="Atlas" in the header, the placeholder and the answers, with locale en-GB.

Open

Brand, sidebar closed

tone="brand" on a new chat with the history collapsed.

Open

Loading

The history, the title and the thread as skeletons.

Dependencies

motionlucide-reactavatarbuttonchat-messagechat-threadconversation-listdrawerdropdown-menuinline-editmarkdownmodel-pickerprompt-inputreasoning-indicatorsuggestion-chipstoasttool-call-timelinetooltipusage-meteruse-controllable-stateuse-media-queryuse-shortcutai-chatdate-utilsmotionnavigationrelative-timetonesui-config

Files

  • components/blocks/ai-chat-page.tsx
  • components/blocks/ai-chat-page-data.ts

FAQ

Is the React AI Chat Page block free?

The preview, props and docs are free; copying the source needs a Pro plan. See plans.

How do I install AI Chat Page?

Run npx wingo-ui@latest add ai-chat-page. It also adds the Wingo UI items it builds on (Avatar, Button, Chat Message, Chat Thread, Conversation List and 22 more) and the npm packages motion and lucide-react. With shadcn, add the @wingo-ui registry with your API key, then run npx shadcn@latest add @wingo-ui/ai-chat-page.

How does AI Chat Page behave on phones?

The model picker sits in the header's center on desktop and inside the composer on phones.

See also

Chat ThreadConversation ListPrompt InputModel PickerUsage MeterAdmin Shell

More React blocks

API Keys PageAutomation Builder PageCheckout PageCRM Contact PageCRM Pipeline PageError Pages
All 26 React blocks

Articles using this component

  • React AI Chat UI: Streaming, Auto-Scroll and Mobile

    Building UI with AI agents · Oct 9, 2026 · 10 min read

PreviousAdmin ShellNext API Keys Page