AI chat

The whole chat, assembled, set up with props

Three components make it: a provider that holds the conversation, the chat surface, and a launcher that is the button and the panel. Everything below is a prop on one of them, shown on the chat itself, running on a written conversation with no model behind it. How to add it, from one command to the headless engine, is on the AI chat docs page, and the playground stages the same chat with every option on a lever.

On a wide panel the rails sit inline and the welcome spreads out.

Live

Everything on, the way the playground stages it: threads and tabs, the agent panel, the artifact panel, files, mentions and the model picker. Pick a question to see a reply arrive with its reasoning, a card and the follow-up chips.

Open the chat historyAcme Assistant
New chatShow the agent panelShow the artifact panel

How can we help you today?

A written preview. Nothing you type or attach leaves your browser.

Artifacts

Close the artifact

Nothing here yet

What the chat makes for you, like a dashboard or a page, opens in this panel.

Acme Assistant
Projects

Acme Assistant

Connected

Today

Watch the Q3 invoices9:13 am
Started the hourly check on the billing inbox
Draft the renewal note9:04 am
Asked for your choice on the tone
Send the approval request9:02 am
Prepared the request and paused for a yes
Tidy the workspace roles8:58 am
Interrupted

Yesterday

Summarize the standup4:40 pm
Posted the recap to the team channel
Retire the stale flags11:12 am
Opened a pull request for review

Responsive forms

The launcher picks one of three forms from the viewport; nothing to set. Inside the panel, the thread rail and the agent pane sit inline when the panel is at least 720px and 760px wide and open as sheets below that, judged by the panel's own width rather than the screen's. The phone prop on the surface stacks the welcome screen for a handset, which is what the Mobile tab above switches on.

Where the chat sits on each screen
ScreenFormViewport
Wide
Docked beside the page. The page makes room for it.
min-width: 1440px
Tablet
Over the page, with the page dimmed behind it.
Between the two
Phone
The whole screen. The page is hidden until the chat closes.
max-width: 719px

Placement

defaultPlacement on the provider sets where the panel starts. With placementEnabled on the surface, the header carries a menu the visitor moves it from. fullscreenEnabled and closeEnabled add or remove those two controls. A phone has neither the menu nor the resize grips. The chat in the corner of this page has all of them on.

Placements
PlacementWhat it does
Dock right
Docked to the right edge of the page.
Dock left
Docked to the left edge of the page.
Floating
Popped out as a card over the page, moved by its header and sized from its edges.
Full screen
The panel fills the viewport. Opening and closing it is animated.
Adjustable width
A docked panel is dragged between 420px and 655px wide. A floating card grows to 1.2 times its resting size.

Welcome screen

An empty chat shows a greeting for the time of day, the title and tagline, and the starters. The widgets slot puts anything under the composer: links, cards or a whole dashboard, held to one screen or scrolling as a page with widgetsLayout, and as wide as the composer or the panel with widgetsWidth. It all leaves with the first message. The four fillings, side by side in the compact layout: the starters alone, then links, cards and a dashboard in their place, the dashboard running wide.

Acme Assistant
New chat

How can we help you today?

A written preview. Nothing you type or attach leaves your browser.

None
Acme Assistant
New chat

How can we help you today?

A written preview. Nothing you type or attach leaves your browser.

Links
Acme Assistant
New chat

How can we help you today?

A written preview. Nothing you type or attach leaves your browser.

Cards
Acme Assistant
New chat

How can we help you today?

Working now1

Importing last year’s invoices212 of 340 matched2m 13s

Trial signups

Projects3

Workspace revamp4 open tasks1m
Billing cleanupWaiting on finance3d
Launch weekPlan attached5d

To do5

This week

Signups640
Seats in use5 of 12
Messages sent1,284

A written preview. Nothing you type or attach leaves your browser.

Dashboard

Threads and tabs

threads turns the history rail on. Every chat is kept and a new chat is named after its first reply; a chat can be pinned, renamed or deleted from its row. threadsProps sets the rail's brand, profile and whether it starts expanded; the provider's threads option seeds the history, switches the detail lines and pins, and takes the rename, delete and pin callbacks. tabs is a separate switch: a tab per open chat, in sync with the rail, closing back to the welcome screen when the last one goes. On a phone the rail opens as a sheet from the header.

Open the chat historyAcme Assistant
New chat

How can we help you today?

A written preview. Nothing you type or attach leaves your browser.

Acme Assistant
Projects

Agent panel

agent turns the pane on and names its tabs; here, what the agent has done, what is waiting for approval, what is scheduled, and the person's profile. defaultOpen opens it at mount; otherwise the header button does. The tabs and their contents are the host's own. aside takes a render function instead, for a pane of your own. On a phone it opens as a sheet.

Acme Assistant
New chatHide the agent panel

How can we help you today?

A written preview. Nothing you type or attach leaves your browser.

Acme Assistant

Connected

Today

Watch the Q3 invoices9:13 am
Started the hourly check on the billing inbox
Draft the renewal note9:04 am
Asked for your choice on the tone
Send the approval request9:02 am
Prepared the request and paused for a yes
Tidy the workspace roles8:58 am
Interrupted

Yesterday

Summarize the standup4:40 pm
Posted the recap to the team channel
Retire the stale flags11:12 am
Opened a pull request for review

Artifact panel

artifacts turns the panel on, for a reply that makes something too big for a turn: a dashboard, a page, a file. The artifact arrives as a card of kind artifact, so the server sends it like any other card. The thread shows it as a tile, and the tile or the header button opens it beside the conversation. An HTML document or a URL is drawn in a sandboxed frame, with the source behind the Code view; the provider's artifactRenderers draw a kind of your own as live components. Drag the panel's left edge to size it, or expand it to fill the chat. The panel sits beside the conversation from 760px of chat width, and opens as a sheet below that and on a phone. It shares its seat with the agent panel, one at a time.

Acme Assistant
New chatShow the artifact panel

How can we help you today?

A written preview. Nothing you type or attach leaves your browser.

Artifacts

Close the artifact

Nothing here yet

What the chat makes for you, like a dashboard or a page, opens in this panel.

Quick replies

starters open an empty chat, with startersKey deciding when a fresh set is drawn. The provider's followups option names the endpoint or function that writes follow-up questions from each answer, shown under it with a shimmer while they are on their way; fallbackFollowups covers a miss. A chip holds 40 characters; a longer one is dropped rather than cut. Once a chip is sent, its row stays as the record: the sent chip outlined, the rest faded, none of them tappable.

Acme Assistant
New chat

How can we help you today?

A written preview. Nothing you type or attach leaves your browser.

Questions

When a reply needs a decision before it can go on, it ends in a question with the answers to pick, drawn as a question card under the prose in place of the follow-up chips. One answer is a tap, several are ticked and sent together, and a short set is asked a step at a time. The answer is sent as the next message, plain text for the model, and the card stays as the record of the choice. A set of more than one question holds the composer under questionsPlaceholder until it is answered or skipped. On the server, askUser gives the model the tool it asks through; a script attaches a question to a reply, with the replies its answers lead to.

Acme Assistant
New chat

How can we help you today?

A written preview. Nothing you type or attach leaves your browser.

Flow

flow sets which way the conversation reads. The default, top-down, floats each new message to the top of the thread and streams the answer in below it. bottom-up is the classic message thread: turns stack from the bottom, the newest just above the composer, and the view follows the answer down until you scroll up to reread.

Acme Assistant
New chat

How can we help you today?

A written preview. Nothing you type or attach leaves your browser.

Rich content

A reply can carry a card as well as text. The server sends the card as data with a kind, and the provider's renderers map each kind to a component, so any component in this library can sit inside a reply. The demo subpath ships renderers for a chart, a plan, a tool call, a diff, an approval, a source list and a product card; here a chart and a plan.

Acme Assistant
New chat

How can we help you today?

A written preview. Nothing you type or attach leaves your browser.

Live status and reasoning

Built in, driven by the transport's status events. While the model works, its current step shows as a live status above the reply and its reasoning collects underneath, open. When the first words arrive the reasoning folds into one line that says how long it took. The reply streams in at an even pace whatever rate the model sends it at; reduced motion turns the pacing off. This example asks its question over and over, slowed down so the thinking can be read.

Acme Assistant
New chat

How can we help you today?

A written preview. Nothing you type or attach leaves your browser.

Documents

fileAttachments turns files on: the composer's attach button, a paste, or a drop anywhere on the chat, with maxAttachments and maxAttachmentBytes as the limits. A long paste becomes a file of its own. Previews are built in the browser and nothing is uploaded unless the host's transport sends it. In the thread, a sent file is a tile above the message: a picture keeps its own ratio, a document wears its type; several form a grid, and past a limit the rest collapse behind a count. Pressing a tile opens the viewer. mentions supplies the people, files and commands typed with @ and /, and models the picker's list, with lockedModelDescription for one the budget has locked.

Acme Assistant
New chat

How can we help you today?

A written preview. Nothing you type or attach leaves your browser.

Props

Read from the same JSDoc that ships in the package's types. Copy for agents hands your coding agent the same contract.

ChatWidget

ChatWidget props
PropTypeDefaultDescription
fullscreenEnabled
boolean
true
Show the expand toggle. A host whose stage is always a takeover hides it.
closeEnabled
boolean
true
Show the header's close button. A host that seats the chat as the page itself rather than as a panel over one has nothing to close back to, so it turns this off.
placementEnabled
boolean
false
Show the header's Chat position menu (dock right, dock left, floating). Off by default: a host turns it on only when it implements the seats the menu offers, as ChatLauncher does.
compact
boolean
false
Narrow insets for phone-width hosts.
phone
boolean
false
The host is a phone viewport, where the soft keyboard will claim the lower half of the screen the moment the composer is focused. The welcome screen stacks instead of centring the composer: greeting in the middle of the empty thread, starters directly above the composer, composer pinned to the bottom from the first paint.
title
string
Assistant
The header brand name, which also seeds the agent's PixelAvatar. Note: not the native `title` tooltip attribute; ChatWidget spreads no native attributes.
flow
"top-down" | "bottom-up"
top-down
Which way the conversation reads. `top-down` (the default) floats each new turn to the top of the thread and streams the answer in below it. `bottom-up` is the classic message thread: turns stack from the bottom, the newest just above the composer, and the view follows the answer.
placeholder
string
Ask anything
The composer's placeholder text.
questionsPlaceholder
string
Answer the questions above, or skip them
The composer's placeholder while a set of questions holds it: the answer goes in the card, or the card is skipped.
showStarters
boolean
true
Show the conversation starters on the welcome screen.
logo
string | null
null
The header mark's image src; null (the default) shows the name alone.
tagline
string
How can I help you today?
The welcome screen's line under the greeting.
starters
Starter[]
The conversation starters: a few pre-written questions. Each must fit the chip budget (SUGGESTION_MAX_CHARS); one that does not is dropped rather than clipped.
startersKey
string
Keys the starters' staged reveal: a new key replays the generation beat, the same key shows the set standing. A host whose starters follow the page passes the pathname.
composerActions
ReactNode
Replaces the composer's leading actions (the model picker).
models
ChatModelOption[]
The models the picker offers. The pick rides on each send as a wire value; the server resolves it. Omit for no picker.
defaultModel
string
The picker's selection before the server has reported its default. Defaults to the first model.
lockedModelDescription
string
Paused for today to stay in budget.
The one line a locked model shows in place of its description.
fileAttachments
boolean
false
Let the visitor attach files: an attach button, paste, drop anywhere on the chat, and long pastes folded into a tile. Files are read in the browser for previews; what reaches the transport is names and kinds.
maxAttachments
number
10
Most files the visitor may queue on one message.
maxAttachmentBytes
number
50 * 1024 * 1024
Largest file the visitor may queue, in bytes.
mentions
MentionSource[]
What the visitor can reference while typing: one source per trigger character, drawn as tags in the composer and in the sent bubble.
threads
RailSlot
A session-history rail. `true` seats the built-in ChatThreads over the provider's thread lifecycle; a render prop seats your own. Wide hosts seat it as an inline left rail, narrow ones summon it from a header hamburger as a slide-over sheet behind a scrim.
threadsProps
Omit<ChatThreadsProps, "close" | "overlay">
Props for the built-in threads rail when `threads` is `true`.
tabs
ReactNode
An open-sessions tab strip as its own row under the header. `true` seats the built-in ChatTabs; a node seats your own.
tabsProps
ChatTabsProps
Props for the built-in tab strip when `tabs` is `true`: its name, its close buttons' names and its spoken statuses.
aside
((ctx: { overlay: boolean; close: () => void; }) => ReactNode)
A companion rail on the trailing edge, the mirror of `threads`: a render prop for your own pane, seated inline on a wide host and raised as a bottom sheet from a header button on a narrow one. For the built-in pane pass `agent` instead.
agent
ChatAgentOptions
The built-in agent pane: who the agent is and what it has been doing. Seated like `aside`.
artifacts
boolean
false
Seat the artifact panel: a reply that carries an artifact draws a tile in the thread, and the tile (or the header's artifact button) opens the artifact beside the conversation on a wide host and as a bottom sheet on a narrow one. The trailing seat holds one panel at a time, so an open artifact stands in for the agent pane. Off, none of it exists: no header button, no tile, no panel.
contextLabel
string | null
The composer's context note, naming what the chat is looking at. Omit for none. The note's wording comes from `contextNote`.
contextNote
((title: string) => string)
(title: string) => `Looking at “${title}”`
The composer's context note, written from `contextLabel`. Defaults to `Looking at “<title>”`.
attachHint
((maxSize: string, maxFiles: number, maxBytes: number) => string)
(maxSize: string, maxFiles: number) => …
The second line of the drop overlay with attachments on, written from the limits: the largest file as text ("50 MB"), the most files per message, and the largest file in bytes for a host that formats sizes itself. Defaults to `Up to <maxSize> each · <maxFiles> files max`.
greetings
Partial<GreetingCopy>
The welcome greeting for each part of the visitor's day; a key left out keeps its English. Defaults to "Good morning", "Good afternoon" and "Good evening".
placementLabels
Partial<Record<ChatPlacement, string>>
The Chat position menu's rows, one per seat; a key left out keeps its English. Defaults to "Dock right", "Dock left" and "Floating".
agentStatus
string
Connected
The status line under the agent's name in the agent pane, where `agent` brings no `profile` of its own. Defaults to "Connected".
artifactPanelTitle
string
Artifacts
The artifact panel's title while nothing is on stage. Defaults to "Artifacts".
artifactEmptyTitle
string
Nothing here yet
The artifact panel's empty-state heading. Defaults to "Nothing here yet".
artifactEmptyDescription
string
What the chat makes for you, like a dashboard or a page, opens in this panel.
The artifact panel's empty-state description. Defaults to "What the chat makes for you, like a dashboard or a page, opens in this panel."
widgets
ReactNode
A widget slot on the welcome screen, under the composer and its starters. It takes any content and keeps its natural height, so the composer rides up by half of it instead of holding dead centre: the empty chat reads as a home page rather than a blank prompt. It leaves with the first message, like the rest of the welcome dressing.
widgetsLayout
"scroll" | "fit"
fit
How the widget slot takes its room. `fit` keeps the welcome screen to one viewport: the widgets hold their height and the composer rides up to make room. `scroll` turns the welcome screen into a page: the greeting and composer take the opening of the viewport, the widgets run on below the fold, and the whole welcome scrolls as one.
widgetsWidth
"column" | "wide"
column
How wide the widget slot runs. `column` holds it to the composer's bounding box; `wide` lets it run past them, for a dashboard.
disclaimer
ReactNode
Answers may be wrong.
The quiet line pinned to the widget's floor: what the chat is and where its policy lives.
startersLabel
string
Conversation starters
Accessible name of the welcome screen's conversation starters. Defaults to "Conversation starters".
newChatLabel
string
New chat
Accessible name of the header's new-chat button. Defaults to "New chat".
showAgentLabel
string
Show the agent panel
Accessible name of the agent-pane toggle while the pane is closed. Defaults to "Show the agent panel".
hideAgentLabel
string
Hide the agent panel
Accessible name of the agent-pane toggle while the pane is open. Defaults to "Hide the agent panel".
closeAgentLabel
string
Close the agent panel
Accessible name of the agent pane's own close button, and of the scrim that closes the pane's bottom sheet. Defaults to "Close the agent panel".
showArtifactLabel
string
Show the artifact panel
Accessible name of the artifact-panel toggle while the panel is closed. Defaults to "Show the artifact panel".
hideArtifactLabel
string
Hide the artifact panel
Accessible name of the artifact-panel toggle while the panel is open. Defaults to "Hide the artifact panel".
closeArtifactLabel
string
Close the artifact panel
Accessible name of the scrim that closes the artifact panel's bottom sheet. Defaults to "Close the artifact panel".
placementLabel
string
Chat position
Accessible name of the Chat position menu's button, and the heading of its group. Defaults to "Chat position".
enterFullscreenLabel
string
Enter full screen
Accessible name of the expand toggle in panel view. Defaults to "Enter full screen".
exitFullscreenLabel
string
Exit full screen
Accessible name of the expand toggle in full-screen view. Defaults to "Exit full screen".
closeLabel
string
Close chat
Accessible name of the header's close button. Defaults to "Close chat".
openThreadsLabel
string
Open the chat history
Accessible name of the header button that opens the chat-history sheet on a narrow host. Defaults to "Open the chat history".
closeThreadsLabel
string
Close the chat history
Accessible name of the scrim that closes the chat-history sheet. Defaults to "Close the chat history".
modelPickerLabel
string
Choose a model
Accessible name of the composer's model picker. Defaults to "Choose a model".
sendLabel
string
Send
Accessible name of the composer's send button. Defaults to "Send".
copyResponseLabel
string
Copy response
Accessible name of a reply's copy button. Defaults to "Copy response".
copiedResponseLabel
string
Copied
Accessible name of a reply's copy button once the copy has landed. Defaults to "Copied".
copiedAnnouncementLabel
string
Copied to clipboard
What screen readers hear once a reply has been copied. Defaults to "Copied to clipboard".
goodResponseLabel
string
Good response
Accessible name of a reply's thumbs-up button. Defaults to "Good response".
badResponseLabel
string
Bad response
Accessible name of a reply's thumbs-down button. Defaults to "Bad response".
followupsLabel
string
Follow-up questions
Accessible name of the follow-up question row under a finished answer. Defaults to "Follow-up questions".
pastedTextLabel
string
The name a long paste's tile wears in the composer and the sent message. Defaults to "Pasted text".
reasoningLabel
((durationSeconds: number) => string)
The reasoning disclosure's summary once the thinking is over, given the seconds it took when known. Defaults to "Thought for <n>s", or "Thought process" with no duration.
composerLabels
Pick<ComposerProps, "aria-label" | "attachmentTileLabels" | "attachLabel" | "dropLabel" | "filesLabel" | "formatFileAnnouncement" | "formatMentionAnnouncement" | "stopLabel">
The composer's words, over Composer's English defaults: the attach button ("Attach files"), the drop overlay on the shell ("Drop files to attach"), the queued files' list ("Attachments") and their tiles (`attachmentTileLabels`), the stop button ("Stop generating"), the text field's name ("Message"), and the sentences announced when files or mention matches change. The send button's name is `sendLabel`.
attachmentDropZoneLabels
Pick<AttachmentDropZoneProps, "label">
The drop overlay's headline when a file is dragged over the chat with attachments on, over AttachmentDropZone's "Drop files to attach". Its second line is `attachHint`.
attachmentGroupLabels
Pick<AttachmentGroupProps, "label" | "showMoreLabel" | "showLessLabel" | "attachmentTileLabels" | "attachmentViewerLabels">
The words of the files on a sent message, over AttachmentGroup's English defaults: the list's name ("Attachments"), the overflow buttons ("Show 3 more", "Show fewer"), the tiles' status lines (`attachmentTileLabels`) and the viewer a pressed file opens in (`attachmentViewerLabels`).
chatThreadLabels
Pick<ChatThreadProps, "ariaLabel" | "jumpLabel">
The conversation's names, over ChatThread's English defaults: the scrolling region ("Conversation") and the scroll-to-latest control ("Scroll to the latest message").
modelPickerLabels
Pick<ModelPickerProps, "placeholder" | "listLabel">
The model picker's words, over ModelPicker's English defaults: the open list's name ("Model") and the trigger's text when nothing is selected ("Choose a model"). The trigger's own name is `modelPickerLabel`.
artifactPanelLabels
Pick<ArtifactPanelProps, "collapseLabel" | "closeLabel" | "expandLabel" | "previewLabel" | "codeLabel" | "viewLabel" | "codeBlockLabels">
The artifact panel's words, over ArtifactPanel's English defaults: the view switch ("Preview", "Code", "Artifact view"), the expand and close buttons ("Expand the artifact", "Collapse the artifact", "Close the artifact") and the code view's CodeBlock (`codeBlockLabels`).
agentRailLabels
Pick<AgentRailProps, "tabsLabel">
The agent pane's words, over AgentRail's English defaults: the tab strip's name ("Agent views"). The pane's close is `closeAgentLabel`.
questionCardLabels
Partial<QuestionCardLabels>
The words of a question card a reply ends in, over QuestionCard's English defaults: the step count ("1 of 3"), the buttons ("Back", "Next", "Send", "Skip"), the records ("Skipped", "Not answered", "(chosen)"), the pick lines ("Choose one") and the "Something else" row.
questionSummaryLabels
Pick<QuestionSummaryProps, "missingLabel">
The words of a sent set of answers, over QuestionSummary's English default: what stands in for a question left without an answer ("No answer").
codeBlockLabels
(Pick<CodeBlockProps, "copyLabel" | "copyText" | "copiedLabel"> & { codeLabel?: ((language: string) => string); }) | undefined
The words of a reply's fenced code, over CodeBlock's English defaults: the copy button ("Copy code", "Copy", "Copied"), and the code region's name, given the fence's language ("Code: bash", or "Code" with none).
promptSuggestionsLabels
Pick<PromptSuggestionsProps, "chosenLabel">
The follow-up row's words, over PromptSuggestions' English default: the hidden text read after the sent suggestion ("(chosen)"). The row's name is `followupsLabel`.

ChatProvider

ChatProvider props
PropTypeDefaultDescription
transport
ChatTransport
Where the conversation goes. Defaults to the fetch transport against `endpoint`, carrying the visitor's model pick. A script from `scriptChat()` runs the widget with no backend at all.
endpoint
string
/api/chat
The endpoint the default transport posts to.
defaultPlacement
ChatPlacement
right
The seat the panel opens in.
followups
string | false | FollowupsSource
/api/chat/followups
Where follow-up questions come from after an answer commits: a source function, an endpoint for the built-in fetcher, or `false` for none: with `false` no chips show under an answer at all, not even the written `fallbackFollowups`. Defaults to the fetcher against `/api/chat/followups`.
fallbackFollowups
readonly string[]
[ …
The written questions offered when the source returns none or fails. Unused when `followups` is `false`.
feedback
string | false | FeedbackSink
/api/chat/feedback
Where a thumbs verdict goes: a sink function, an endpoint for the built-in poster, or `false` to hide the thumbs. Defaults to the poster against `/api/chat/feedback`. Thumbs only ever show on a turn the server logged (one with an exchange id).
renderers
ChatCardRenderers
Draws `card` events by kind.
artifactRenderers
ChatArtifactRenderers
Draws an artifact's preview by kind, for artifacts that are live React content rather than a document or a URL.
renderLink
ChatLinkRenderer
(props) => <DefaultChatLink {...props} />
Renders a same-site link in an answer. The default renders through the nearest LinkProvider's link component, else a plain anchor; passing this wins over both.
isInternalHref
((href: string) => boolean)
(href: string) => INTERNAL_PATH.test(href)
Which hrefs in an answer become links. Everything else renders as text.
threads
ThreadsOptions
Seeds the thread lifecycle behind the `threads` and `tabs` slots.
placeholders
Partial<ChatPlaceholderCopy>
Replacement copy for the words the hook writes itself, merged over the English defaults: the status line of a reply that has not started ("Thinking") and the placeholder replies for an empty, stopped or failed turn.

ChatLauncher

ChatLauncher props
PropTypeDefaultDescription
label
string
Ask
The floating button's text.
icon
string
forum
The button's icon.
summary
(AiButtonSummary & { chips?: { id: string; label: string; prompt: string; }[]; })
A TLDR panel the button summons on hover: a pre-written summary and prompt chips. A tapped chip opens the chat and sends the chip's `prompt`. The launcher hands it to the closed button's AiButton, which opens the panel on pointer hover; it does no device or hydration gating of its own, so a host that wants the panel on hover-capable devices only, or kept out of server HTML, passes `summary` only there.
hidden
boolean
false
Render nothing at all: for routes that carry no chrome. Note: not the native `hidden` attribute, which keeps an element mounted and only hides it; the launcher unmounts its button and panel, and spreads no native attributes.
panelId
string
ds-chat-panel
The panel's DOM id, for a host control's `aria-controls`.
hostAttribute
string | false
data-chat
The attribute the launcher writes on `<html>` to say how the panel sits (`docked`, `docked-left`, `takeover`), so the host's stylesheet can pad the page or hide it. `false` writes none.
panelLabel
string
Chat
Accessible name for the panel.
aiButtonLabels
Pick<AiButtonProps, "summaryRegionLabel" | "dismissLabel" | "suggestionsLabel">
The words of the floating button's summary panel, over AiButton's English defaults: the panel's name, given the summary's title ("Summary: <title>"), its dismiss button ("Dismiss summary") and its chips' group ("Suggested prompts").
widget
Omit<ChatWidgetProps, "compact" | "fullscreenEnabled" | "placementEnabled" | "phone">
Everything the widget takes. The launcher sets the responsive ones itself.
children
ReactNode
Rendered inside the panel after the widget: for a host's extra chrome.

ChatThreads

ChatThreads props
PropTypeDefaultDescription
overlay*
boolean
The widget seated the rail as a sheet over the conversation rather than beside it.
close*
() => void
Closes the sheet; a no-op on the inline rail.
logo
ReactNode
The brand row's mark, in both seats.
logoText
string
The brand row's text. Shown only on the sheet, where the chat header is hidden behind it; the inline rail leaves it out.
profile
ThreadPanelProfile
The signed-in person, shown on the inline rail.
collapsible
boolean
true
Whether the inline rail can collapse to its icon strip.
defaultExpanded
boolean
false
Whether the inline rail starts expanded. Defaults to `false`: it starts collapsed to its icon strip. The sheet, and a rail that is not `collapsible`, always show expanded.
historyLabel
string
Chat history
Accessible heading over the history.
threadPanelLabels
Pick<ThreadPanelProps, "statusLabels" | "collapseLabel" | "expandLabel" | "pinnedLabel" | "threadMenuLabel" | "renameLabel" | "projectsLabel" | "newProjectLabel">
The words the ThreadPanel writes, merged over its English defaults: the spoken pin and status text ("Pinned", "Working"…), each row's menu trigger ("Thread options"), the rename field ("Rename thread"), the projects header and its add button ("Projects", "New project"), and the collapse toggle ("Collapse the panel", "Expand the panel"). The history's own name is `historyLabel`.
actionLabels
Partial<Record<"pin" | "unpin" | "rename" | "delete", string>>
The rows of each thread's menu, by action; a key left out keeps its English. Defaults to "Pin", "Unpin", "Rename" and "Delete".

ChatTabs

ChatTabs props
PropTypeDefaultDescription
ariaLabel
string
Open chats
Accessible name for the tab strip.
closeLabel
string | ((title: string) => string)
Close chat
Accessible name of each tab's close button. A string is followed by a colon and the tab's title; a function is given the title and returns the whole name. Defaults to "Close chat".
statusLabels
Partial<Record<ThreadTabStatus, string>>
Spoken text for each tab's status, merged over ThreadTabs' English defaults (Working, Unread, Needs input, Failed).

ChatAgentPane

ChatAgentPane props
PropTypeDefaultDescription
profile*
AgentRailProfile
The agent this pane belongs to: the portrait block at the top.
tabs*
AgentRailTab[]
The panes, in display order: activity, approvals, automations, personalisation, or whatever the agent has.
value
string
The tab on stage, when the host owns the state; otherwise the pane keeps its own, seeded from `defaultValue`.
defaultValue
string
The tab on stage first when the pane keeps its own state. Defaults to the first tab.
onValueChange
((id: string) => void)
Fires with the chosen tab's id.
activeTab
string
Legacy name for `value`. Deprecated: Use `value` instead.
onTabChange
((id: string) => void)
Legacy change callback; fires alongside `onValueChange`. Deprecated: Use `onValueChange` instead.
overlay*
boolean
The widget seated the pane as a bottom sheet, where it fills the width instead of holding its own column.
onClose
(() => void)
Fires from the pane's own close button, a cross in its top trailing corner. Omit for a pane with no close of its own.
closeLabel
string
Close the agent panel
Accessible name of the pane's own close button. Defaults to "Close the agent panel".
agentRailLabels
Pick<AgentRailProps, "tabsLabel">
The words the AgentRail writes, merged over its English defaults: the tab strip's name ("Agent views").

ChatArtifactPane

ChatArtifactPane props
PropTypeDefaultDescription
artifact*
ChatArtifact | null
The artifact on stage, or null for the empty state: the panel opened before the conversation has made anything.
expanded
boolean
Whether the widget is showing the pane at its expanded size.
onExpandedChange
((expanded: boolean) => void)
Fires with the next state from the expand toggle; omit where the seat has one size.
onClose
(() => void)
Fires from the pane's close button; omit where another control closes the seat.
emptyPanelTitle
string
Artifacts
The panel's title while nothing is on stage. Defaults to "Artifacts".
emptyTitle
string
Nothing here yet
The empty state's heading. Defaults to "Nothing here yet".
emptyDescription
string
What the chat makes for you, like a dashboard or a page, opens in this panel.
The empty state's description. Defaults to "What the chat makes for you, like a dashboard or a page, opens in this panel."
artifactPanelLabels
Pick<ArtifactPanelProps, "collapseLabel" | "closeLabel" | "expandLabel" | "previewLabel" | "codeLabel" | "viewLabel" | "codeBlockLabels">
The words the ArtifactPanel writes, merged over its English defaults: the view switch's segments and name ("Preview", "Code", "Artifact view"), the expand toggle and close button's names ("Expand the artifact", "Collapse the artifact", "Close the artifact"), and the code view's copy button and region (`codeBlockLabels`).

ChatArtifactCard

ChatArtifactCard props
PropTypeDefaultDescription
artifact*
ChatArtifact
The artifact this tile stands for.

Parts

The chat is built from these components, each with a page of its own.

tsx
// From the npm package
import { ChatWidget } from 'rift-ds/chat';

// Or as source you own, via the shadcn CLI
npx shadcn@latest add https://rift-ds.com/r/ai-chat.json