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.
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.
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.
| Screen | Form | Viewport |
|---|---|---|
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.
| Placement | What 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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
Props
Read from the same JSDoc that ships in the package's types. Copy for agents hands your coding agent the same contract.
ChatWidget
| Prop | Type | Default | Description |
|---|---|---|---|
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
| Prop | Type | Default | Description |
|---|---|---|---|
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
| Prop | Type | Default | Description |
|---|---|---|---|
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
| Prop | Type | Default | Description |
|---|---|---|---|
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
| Prop | Type | Default | Description |
|---|---|---|---|
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
| Prop | Type | Default | Description |
|---|---|---|---|
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
| Prop | Type | Default | Description |
|---|---|---|---|
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
| Prop | Type | Default | Description |
|---|---|---|---|
artifact* | ChatArtifact | The artifact this tile stands for. |
Parts
The chat is built from these components, each with a page of its own.
// 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