Skip to content
SLICES / TECHNICAL FOLIO Nº 001FULL-STACK ASSEMBLIES — OPEN SOURCE

Headless / AI chat

Conversation

Compose ai conversation without managing the chat transport yourself.

138 public parts · 5examples

@slices.sh/ai-chat/headlessView as Markdown ↗

Your design. Our behavior.

Explore the tree to see what each part controls. Gates reveal the relevant state; roots outline their scope.

Behavior / inputGateGenericRenderer · not headlessScope
COMPONENT ANATOMYHover · focus · tap
ONE POSSIBLE DESIGNStatic preview

Chat.Root · Scope

Chat.RootChat.Root publishes the SDK Chat itself, never a copy of its state, and provides a sink for Composer. submit(message) calls sendMessage with message.text and message.attachments as file parts. busy is true while a reply streams or a question or tool decision waits. whenBusy is "queue" unless queue={false}. accept.attachments follows the config's files capability: false for a config without files, so the attachment picker inside Composer renders nothing. A Chat.Root nested in another one with the same config and no chat shares the outer conversation.

Installation

Choose what your component needs. Run these commands in an initialized Next.js app.

0

Before you start

The steps below run in a Next.js app with shadcn set up (it has a components.json). In an existing Next.js app, such as one from create-next-app, set shadcn up first:

npx shadcn@latest init -t next -b base -p nova

Or start fresh: the slices CLI creates the app and sets it up.

npx slices.sh install
1

Install the service registry

Adds services/index.ts, which import "@/services" loads. A provider setup writes the same file, so skip this if your app has one.

npx add services
2

Install the headless library

npm

Add the React parts to your app, then compose them with your own elements.

npm install @slices.sh/ai-chat@^0.1.4 @slices.sh/composer@^0.1.4

Import from @slices.sh/ai-chat/headless.

3

Install the service

Connect the parts to a provider. Skip this step if this service is already configured in your app.

Provider
npx add ai-chat.echo

Adds service configuration and API routes to your app, with the provider dependencies. For a headless composition, add import "@/services" after "use client".

The slices CLI installs the service and provisions its required resources in one command.

Provider setup notes
  • Echo needs nothing. When you want a model: npx shadcn@latest add @slices/ai-chat.vercel, then switch provider in services/ai-chat/default.config.ts.
Optional: Chat media parts
0

Before you start

The steps below run in a Next.js app with shadcn set up (it has a components.json). In an existing Next.js app, such as one from create-next-app, set shadcn up first:

npx shadcn@latest init -t next -b base -p nova

Or start fresh: the slices CLI creates the app and sets it up.

npx slices.sh install
1

Install the headless library

npm

Add the React parts to your app, then compose them with your own elements.

npm install @slices.sh/chat-media

Import from @slices.sh/chat-media/headless.

These parts run locally. No service installation or provisioning is needed.

Optional: Markdown rendering
0

Before you start

The steps below run in a Next.js app with shadcn set up (it has a components.json). In an existing Next.js app, such as one from create-next-app, set shadcn up first:

npx shadcn@latest init -t next -b base -p nova

Or start fresh: the slices CLI creates the app and sets it up.

npx slices.sh install
1

Install the headless library

npm

Add the React parts to your app, then compose them with your own elements.

npm install @slices.sh/markdown

Import from @slices.sh/markdown.

These parts run locally. No service installation or provisioning is needed.

Optional: Migrate chat attachments
0

Before you start

The steps below run in a Next.js app with shadcn set up (it has a components.json). In an existing Next.js app, such as one from create-next-app, set shadcn up first:

npx shadcn@latest init -t next -b base -p nova

Or start fresh: the slices CLI creates the app and sets it up.

npx slices.sh install
1

Install the service registry

Adds services/index.ts, which import "@/services" loads. A provider setup writes the same file, so skip this if your app has one.

npx add services
2

Install the headless library

npm

Add the React parts to your app, then compose them with your own elements.

npm install @slices.sh/chat-attachments

Import from @slices.sh/chat-attachments/headless.

3

Install the service

Connect the parts to a provider. Skip this step if this service is already configured in your app.

Provider
npx add file-storage.local

Adds service configuration and API routes to your app, with the provider dependencies. For a headless composition, add import "@/services" after "use client".

The slices CLI installs the service and provisions its required resources in one command.

Provider setup notes
  • Add .data/ to .gitignore: the bytes and the index live there.
  • This store lives on one disk. A serverless deployment loses the files between requests, so deploy with @slices.sh/file-storage.s3.
  • A screen works in a bucket, a private corner of the config ("files" by default). The config lists the ones its screens work in (`buckets`, which installs grow); list more, or a prefix such as "playground/", in `buckets` in services/file-storage/rules.ts. Any other is not-found.
  • Set maxUploadBytes and accept in services/file-storage/default.config.ts: nothing is capped until you do.

Start small

Parts bring the behavior. Use their default elements, or supply your own with render.

example.tsx
"use client"// services/index.ts comes from https://slices.sh/r/services.json (or any provider setup)import "@/services"import { Chat } from "@slices.sh/ai-chat/headless"import { Composer } from "@slices.sh/composer"export function Example() {  return (    <Chat.Root>      <Chat.Transcript>        <Chat.Thread>          <Chat.Messages>            <Chat.Message>              <Chat.Parts>                <Chat.PartText>{({ text }) => <p>{text}</p>}</Chat.PartText>              </Chat.Parts>            </Chat.Message>          </Chat.Messages>        </Chat.Thread>      </Chat.Transcript>      <Composer.Root>        <Composer.Input aria-label="Message" />        <Composer.Submit>Send</Composer.Submit>      </Composer.Root>    </Chat.Root>  )}

Chat.Root receives Composer's messages. The echo provider lets you try this without a model key.

API reference

Every public part used by this experience is listed below. Gates render children without adding an element. Element parts accept native element props and render; function children receive the state declared in their props. Scopes provide context rather than a visual element.

Chat.StepBoundarygate

Messages repeats once per UIMessage and Message is its element: data-state user or assistant, aria-busy while it is the answer being written, data-invalid when it was cut off. Speaker says who spoke, for screen readers. Parts repeats once per SDK part in the order the model produced them, and each kind has its own gate: PartText is one run of prose, StepBoundary marks a new model step. Stopped renders only for a reply that was cut off, and Continue sends a follow-up prompt that resumes it.

Required scope

Chat.StepBoundary requires Chat.Parts.

Chat.StepBoundary requires Chat.Messages.

Props

1 documented props

Chat.StepBoundary props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { number: number }) => ReactNode)—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/step-boundary.tsx

Chat.Continueaction · <button>

Messages repeats once per UIMessage and Message is its element: data-state user or assistant, aria-busy while it is the answer being written, data-invalid when it was cut off. Speaker says who spoke, for screen readers. Parts repeats once per SDK part in the order the model produced them, and each kind has its own gate: PartText is one run of prose, StepBoundary marks a new model step. Stopped renders only for a reply that was cut off, and Continue sends a follow-up prompt that resumes it.

Required scope

Chat.Continue requires Chat.Root.

Chat.Continue requires Chat.Messages.

Props

3 documented props · Native <button> attributes supported

Chat.Continue props
PropTypeDefault
promptRequired
string—
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/continue.tsx

Chat.ReasoningTimercontent · <span>

PartReasoning gates a reasoning part and hands its children { text, streaming }. ReasoningDisclosure is a native details element, so a find in page can reveal a match. ReasoningTimer gives { seconds, streaming } for "Thought for 4s". Without the reasoning capability the model sends no reasoning parts, and the group renders nothing.

Capability: reasoning

Required scope

Chat.ReasoningTimer requires Chat.PartReasoning.

Props

2 documented props · Native <span> attributes supported

Chat.ReasoningTimer props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { seconds: number | null; streaming: boolean }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/reasoning-timer.tsx

Chat.ReasoningDisclosurecontent · <details>

Native details stays searchable and lets the browser reveal a found match.

Capability: reasoning

Required scope

Chat.ReasoningDisclosure requires Chat.PartReasoning.

Props

2 documented props · Native <details> attributes supported

Chat.ReasoningDisclosure props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/reasoning-disclosure.tsx

Chat.ComposerRootscope

Reuses the containing chat, so embedding a composer never starts a second conversation.

Props

4 documented props

Chat.ComposerRoot props
PropTypeDefault
nameRequired
string—
chat
AiChat—
settings
ChatSettings | null—
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/composer-root.tsx

Chat.ComposerStandalonegate

Today's chat composer parts. In v2 Chat.Root is a sink (whenBusy "queue") and the generic Composer from @slices.sh/composer writes into it. Chat.Composer becomes Composer.Root. Chat.Input becomes Composer.Input, a field named text, wrapped by Dictation.Field when dictation is wanted. Chat.Submit's sending half becomes Composer.Submit. Its stopping half is chat behaviour no generic part can express, so it stays a chat part, Chat.Stop (new in v2): it calls the SDK's stop, is disabled while nothing streams and never unmounts, so focus and layout stay put when a turn ends. Chat.ComposerRoot becomes a nested Chat.Root, which shares the outer conversation for the same config. Chat.ComposerStandalone has no replacement: a pattern that draws Chat.Settings only when it stands alone takes a prop for it.

Props

1 documented props

Chat.ComposerStandalone props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/composer-standalone.tsx

Chat.Rootscope

Chat.Root publishes the SDK Chat itself, never a copy of its state, and provides a sink for Composer. submit(message) calls sendMessage with message.text and message.attachments as file parts. busy is true while a reply streams or a question or tool decision waits. whenBusy is "queue" unless queue={false}. accept.attachments follows the config's files capability: false for a config without files, so the attachment picker inside Composer renders nothing. A Chat.Root nested in another one with the same config and no chat shares the outer conversation.

Props

9 documented props

Chat.Root props
PropTypeDefault
onFeedback
(feedback: ChatFeedback) => void | Promise<void>—
name

The key in services/ai-chat/config.ts: the route the chat talks to when it is handed none. Left out, the config's slug.

string—
config

The config to talk to, "default" when left out.

string—
enabled

Left out or true: required, and a missing service or config throws. "optional": renders its children, and a Composer under it renders nothing. false: off. A capability name requires the service and that capability.

Enabled—
chat

An AI SDK Chat the app made — its id, the messages it opens on, a transport with your headers — which every part reads with useChat({ chat }). Without one, a chat over the installed backend's route.

AiChat—
settings

From chatSession(client, name), bound to the supplied Chat transport.

ChatSettings | null—
queue

The sink's whenBusy: on, a message sent mid-answer is accepted and queued; off, Composer holds it until the chat is free.

booleantrue
rememberApprovals

Enable explicit per-tool consent remembered only for this Chat instance.

booleantrue
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/root.tsx

Chat.Transcriptcontent · <div>

The scroller, and the only one. A second scroller inside it produces a transcript that follows an end nobody can see: the outer one is already at its bottom, and the words arrive somewhere off screen. `role="log"` with `tabIndex` is the pair the APG asks for and the pair this was missing: the role makes arriving messages announce themselves, and the tab stop is the only way a keyboard reaches a scrolling region whose contents — bubbles, avatars — are not focusable. The busy flag belongs on the message being written and not here. On the region it held back everything the region was for: a polite log defers what arrives inside a busy node, so the question the person just sent and the note saying an answer is coming were both announced late or not at all — the two announcements that matter most, suppressed to defer the one that already defers itself. → components/headless/ai-chat/message.tsx The reader's own wheel, touch, keys and scrollbar are what take the transcript away from where the scroller put it; the scroller's own moves never do. → hooks/ai-chat/use-follow.ts

Required scope

Chat.Transcript must be inside <Chat.Root>.

Props

2 documented props · Native <div> attributes supported

Chat.Transcript props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { following: boolean }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/transcript.tsx

Chat.Threadcontent · <div>

Custom renderers retain MessageScroller.Content so anchor children and resizing stay registered.

Props

2 documented props · Native <div> attributes supported

Chat.Thread props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/thread.tsx

Chat.Messagesscope

The transcript's messages, each in its own scope, exactly as the AI SDK holds them. The repeat is a part rather than a `map` in the pattern, because a message is where the looks change most and the iteration never does: a skin decides what a row is, and this decides what the rows are.

Required scope

Chat.Messages must be inside <Chat.Root>.

Props

1 documented props

Chat.Messages props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/messages.tsx

Chat.Messagecontent · <div>

Messages repeats once per UIMessage and Message is its element: data-state user or assistant, aria-busy while it is the answer being written, data-invalid when it was cut off. Speaker says who spoke, for screen readers. Parts repeats once per SDK part in the order the model produced them, and each kind has its own gate: PartText is one run of prose, StepBoundary marks a new model step. Stopped renders only for a reply that was cut off, and Continue sends a follow-up prompt that resumes it.

Required scope

Chat.Message must be inside <Chat.Messages>.

Chat.Message must be inside <Chat.Root>.

Props

3 documented props · Native <div> attributes supported

Chat.Message props
PropTypeDefault
optimizeHistory
booleantrue
children

Content rendered inside this part.

ReactNode | ((state: MessageState) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/message.tsx

Chat.Speakercontent · <span>

Who said it, in words. Colour and alignment are the only thing that told the two apart, which is nothing at all to a screen reader and very little on a low-contrast theme. The default skin hides this visually and leaves it in the accessibility tree, where it is the difference between a conversation and a run of anonymous paragraphs.

Required scope

Chat.Speaker must be inside <Chat.Messages>.

Props

2 documented props · Native <span> attributes supported

Chat.Speaker props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { role: AiChatMessage["role"] }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/speaker.tsx

Chat.Partsscope

A message's parts, in the order the model produced them, exactly as the AI SDK holds them. The order is the content. Reasoning before an answer, a tool call between two halves of one, a citation after both — a transcript that grouped by kind would say the model did things in an order it did not. Each kind gates itself inside here, and a kind no gate draws — a step boundary, an app's own `data-*` part — draws nothing. → docs/rules/states-gate-themselves.md

Required scope

Chat.Parts must be inside <Chat.Messages>.

Props

1 documented props

Chat.Parts props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/parts.tsx

Chat.PartTextgate

One run of prose, the SDK's `text` part. A message has several when something happened between them. The role comes with it because whose text this is decides whether it is markup: a model writes markdown and means it, and a person who types `2 * 3 * 4` means three numbers.

Required scope

Chat.PartText must be inside <Chat.Parts>.

Chat.PartText must be inside <Chat.Messages>.

Chat.PartText requires Chat.Root.

Props

1 documented props

Chat.PartText props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: PartTextState) => ReactNode)—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/part-text.tsx

Chat.PartReasoninggate

A model thinking out loud, the SDK's `reasoning` part, and whether it has stopped. `streaming` is what lets one block be open while it fills and closed once the answer starts, which is the convention every product settled on: the trace is interesting while it is the only thing happening and noise the moment it is not. A trace the SDK still holds as `streaming` on an answer nobody is writing was cut off, and is over too.

Capability: reasoning

Required scope

Chat.PartReasoning must be inside <Chat.Parts>.

Chat.PartReasoning must be inside <Chat.Messages>.

Chat.PartReasoning must be inside <Chat.Root>.

Props

1 documented props

Chat.PartReasoning props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: PartReasoningState) => ReactNode)—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/part-reasoning.tsx

Chat.Usagegate

What the turn cost, where the provider said: the SDK's usage, as the route put it on the message's metadata when the turn finished. Nothing at all where it did not: this field went years declared and never written, and the website that needed it estimated from the length of the text. An estimate on screen is a number people plan against. → docs/rules/capability-honesty.md

Capability: usage

Required scope

Chat.Usage must be inside <Chat.Messages>.

Props

1 documented props

Chat.Usage props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { usage: LanguageModelUsage }) => ReactNode)—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/usage.tsx

Chat.ContextUsagegate

Model, Timing and Usage read what the route wrote into the message metadata: which model answered, how long it took, the SDK's LanguageModelUsage. ContextUsage gives { tokens, capacity, percent } for the last request while the chat is idle. Each one is null, and renders nothing, when the provider did not report the value.

Capability: usage

Required scope

Chat.ContextUsage must be inside <Chat.Root>.

Props

1 documented props

Chat.ContextUsage props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: UsageState) => ReactNode)—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/context-usage.tsx

Chat.Modelgate

Model, Timing and Usage read what the route wrote into the message metadata: which model answered, how long it took, the SDK's LanguageModelUsage. ContextUsage gives { tokens, capacity, percent } for the last request while the chat is idle. Each one is null, and renders nothing, when the provider did not report the value.

Capability: usage

Required scope

Chat.Model must be inside <Chat.Messages>.

Props

1 documented props

Chat.Model props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { model: string }) => ReactNode)—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/model.tsx

Chat.Timinggate

Model, Timing and Usage read what the route wrote into the message metadata: which model answered, how long it took, the SDK's LanguageModelUsage. ContextUsage gives { tokens, capacity, percent } for the last request while the chat is idle. Each one is null, and renders nothing, when the provider did not report the value.

Capability: usage

Required scope

Chat.Timing must be inside <Chat.Messages>.

Props

1 documented props

Chat.Timing props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { timing: NonNullable<AiChatMetadata["timing"]> }) => ReactNode)—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/timing.tsx

Chat.Stoppedgate

This reply was cut off, and somebody should be told in words. Fading the text was the whole account of it before, which is a contrast regression that says nothing: the reader could not tell whether they had stopped it, the model had, or the network went. → components/headless/ai-chat/writing.ts

Required scope

Chat.Stopped must be inside <Chat.Messages>.

Chat.Stopped must be inside <Chat.Root>.

Props

1 documented props

Chat.Stopped props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { reason: "length" | "interrupted" }) => ReactNode)—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/stopped.tsx

Chat.Composeraction · <form>

Today's chat composer parts. In v2 Chat.Root is a sink (whenBusy "queue") and the generic Composer from @slices.sh/composer writes into it. Chat.Composer becomes Composer.Root. Chat.Input becomes Composer.Input, a field named text, wrapped by Dictation.Field when dictation is wanted. Chat.Submit's sending half becomes Composer.Submit. Its stopping half is chat behaviour no generic part can express, so it stays a chat part, Chat.Stop (new in v2): it calls the SDK's stop, is disabled while nothing streams and never unmounts, so focus and layout stay put when a turn ends. Chat.ComposerRoot becomes a nested Chat.Root, which shares the outer conversation for the same config. Chat.ComposerStandalone has no replacement: a pattern that draws Chat.Settings only when it stands alone takes a prop for it.

Required scope

Chat.Composer must be inside <Chat.Root>.

Props

2 documented props · Native <form> attributes supported

Chat.Composer props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/composer.tsx

Chat.Inputinput · <textarea>

A textarea rather than an input, because Shift+Enter has to mean something. No `rows`: the skin sizes it with `field-sizing: content`, so it grows with the message and stops at a maximum. A fixed row locked every paragraph anyone ever wrote into a thirty-six pixel slit, with the browser's own resize handle taken away.

Required scope

Chat.Input must be inside <Chat.Root>.

Props

2 documented props · Native <textarea> attributes supported

Chat.Input props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/input.tsx

Chat.Submitaction · <button>

One control that sends, and stops what it sent with the SDK's `stop`. The composer's only submit, and the only button that ever occupies this spot. A separate stop button had to appear between send and its neighbour mid-turn, which moved the most used control in the component under a cursor already on its way down; it also unmounted itself the instant the turn ended, dropping focus to the body if anyone had tabbed to it. Morphing solves both: the element is the same element, and it is `type="submit"` only while submitting is what it does. → docs/rules/one-submit-per-form.md It stops an answer while there is nothing to send, and sends while there is — which is the only reading that leaves the queue reachable by touch. Otherwise the one button beside the box said "stop" the whole time an answer was arriving, so a follow-up typed on a phone could be sent only from the software keyboard's own return key, and the control right next to it did something else. Where the composer refuses a second message outright (`queue` off) there is nothing to send by definition, so this is stop again.

Required scope

Chat.Submit must be inside <Chat.Root>.

Props

2 documented props · Native <button> attributes supported

Chat.Submit props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { stopping: boolean }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/submit.tsx

Chat.Stopaction · <button>

Stops a reply that is streaming. Stopping is the chat's own behaviour, so it is not a mode of `Composer.Submit`: no generic part can express it. It is disabled while nothing streams, never unmounted: a button that came and went with every turn moved the controls beside it under a cursor already on its way, and dropped focus to the body when the turn ended with it focused.

Required scope

Chat.Stop must be inside <Chat.Root>.

Props

2 documented props · Native <button> attributes supported

Chat.Stop props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/stop.tsx

Chat.Suggestionsgate

Starters, and only on an empty transcript. Once there is a conversation they are no longer suggestions, they are a row of buttons competing with what the person was about to type.

Required scope

Chat.Suggestions must be inside <Chat.Root>.

Props

1 documented props

Chat.Suggestions props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/suggestions.tsx

Chat.FollowUpsgate

Only the last completed answer can suggest what comes next in the active branch.

Required scope

Chat.FollowUps requires Chat.Root.

Props

1 documented props

Chat.FollowUps props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { prompts: string[] }) => ReactNode)—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/follow-ups.tsx

Chat.Suggestionaction · <button>

Sends its own text. It goes through the composer rather than the chat, so a suggestion queued behind a running turn waits exactly as a typed message does.

Required scope

Chat.Suggestion must be inside <Chat.Root>.

Props

3 documented props · Native <button> attributes supported

Chat.Suggestion props
PropTypeDefault
textRequired
string—
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/suggestion.tsx

Chat.JumpToLatestaction · <button>

Rendered only once the reader has scrolled the transcript away from its end.

Required scope

Chat.JumpToLatest must be inside <Chat.Root>.

Props

2 documented props · Native <button> attributes supported

Chat.JumpToLatest props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/jump-to-latest.tsx

Chat.Emptygate

Nothing has been said yet. Where a greeting and the starters go.

Required scope

Chat.Empty must be inside <Chat.Root>.

Props

1 documented props

Chat.Empty props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/empty.tsx

Chat.Waitinggate

Sent, and nothing back yet: the SDK's `submitted`. Its own gate rather than a flag on a wider one, so the condition lives where the rule wants it and the pattern never writes `waiting ? … : null`. Once the words start arriving they are the answer to "is anything happening", and this renders nothing. → docs/rules/states-gate-themselves.md It belongs inside `Chat.Transcript`, whose `role="log"` announces what arrives in it. A second live region around this note would have a screen reader say it twice.

Required scope

Chat.Waiting must be inside <Chat.Root>.

Props

1 documented props

Chat.Waiting props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/waiting.tsx

Chat.Failedgate

The turn was refused — the SDK's `error` status — and the child is told which refusal it was. The slug reaches the screen because the common ones want different things: a quota refusal wants an upgrade link, an outage wants the retry button, and an unknown chat wants a developer to open `services/ai-chat/config.ts`. One banner for all three would be three lies. → docs/rules/capability-honesty.md

Required scope

Chat.Failed must be inside <Chat.Root>.

Props

1 documented props

Chat.Failed props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { error: ChatErrorSlug; retryIn: number }) => ReactNode)—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/failed.tsx

Chat.TryAgainaction · <button>

One gate per state of the conversation, so pattern code never branches on status. Empty: nothing has been said. Waiting: the SDK's submitted, sent with nothing back yet; it belongs inside Chat.Transcript, whose log announces it. Failed: the SDK's error status with the refusal slug (unauthorized, quota-exceeded, unknown-chat…); it belongs outside the scroller so a refusal never renders below the fold. TryAgain: regenerate() from inside Failed. Unavailable: the one part that renders when Chat.Root is enabled="optional" and ai-chat is not configured, for a sentence saying so.

Required scope

Chat.TryAgain must be inside <Chat.Root>.

Props

2 documented props · Native <button> attributes supported

Chat.TryAgain props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/try-again.tsx

Chat.Unavailablegate

No chat backend is installed at all, and the screen was handed no chat. Distinct from a refused turn, because nothing the person does will help: the app is missing an implementation, and the only useful sentence names the command that adds one.

Required scope

Chat.Unavailable must be inside <Chat.Root>.

Props

1 documented props

Chat.Unavailable props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/unavailable.tsx

Chat.ToolErrorgate

PartTool gates one tool-<name> or dynamic-tool part over the SDK's seven states and hands { toolName, state }. ToolRenderer lets the app draw a tool's body from a renderers map; approval controls stay outside it. ToolInput, ToolOutput and ToolError gate the input, the output and the error text. A config without tools never produces these parts.

Capability: tools

Required scope

Chat.ToolError requires Chat.Parts.

Props

1 documented props

Chat.ToolError props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { value: string }) => ReactNode)—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/tool-error.tsx

Chat.ToolOutputgate

PartTool gates one tool-<name> or dynamic-tool part over the SDK's seven states and hands { toolName, state }. ToolRenderer lets the app draw a tool's body from a renderers map; approval controls stay outside it. ToolInput, ToolOutput and ToolError gate the input, the output and the error text. A config without tools never produces these parts.

Capability: tools

Required scope

Chat.ToolOutput requires Chat.Parts.

Props

1 documented props

Chat.ToolOutput props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { value: unknown }) => ReactNode)—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/tool-output.tsx

Chat.ToolInputgate

PartTool gates one tool-<name> or dynamic-tool part over the SDK's seven states and hands { toolName, state }. ToolRenderer lets the app draw a tool's body from a renderers map; approval controls stay outside it. ToolInput, ToolOutput and ToolError gate the input, the output and the error text. A config without tools never produces these parts.

Capability: tools

Required scope

Chat.ToolInput requires Chat.Parts.

Props

1 documented props

Chat.ToolInput props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { value: unknown }) => ReactNode)—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/tool-input.tsx

Chat.ToolRendererscope

Render only the tool body; approval controls stay outside the app's renderer.

Capability: tools

Required scope

Chat.ToolRenderer requires Chat.Parts.

Props

2 documented props

Chat.ToolRenderer props
PropTypeDefault
renderers
ToolRenderers—
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/tool-renderer.tsx

Chat.ForgetApprovalaction · <button>

For a tool declared with needsApproval. PartApproval is the request, with ApprovalReason, Approve, Deny and AlwaysAllow (only with rememberApprovals). Answering calls the SDK's addToolApprovalResponse. ApprovalError says the answer did not reach the server. ApprovalReceipt replaces the controls once answered, RememberedApproval marks a call allowed by a remembered consent, and ForgetApproval takes that consent back. While a decision is pending the queue waits for it.

Capability: toolApproval

Required scope

Chat.ForgetApproval requires Chat.Root.

Chat.ForgetApproval requires Chat.Parts.

Props

2 documented props · Native <button> attributes supported

Chat.ForgetApproval props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/forget-approval.tsx

Chat.RememberedApprovalcontent · <span>

For a tool declared with needsApproval. PartApproval is the request, with ApprovalReason, Approve, Deny and AlwaysAllow (only with rememberApprovals). Answering calls the SDK's addToolApprovalResponse. ApprovalError says the answer did not reach the server. ApprovalReceipt replaces the controls once answered, RememberedApproval marks a call allowed by a remembered consent, and ForgetApproval takes that consent back. While a decision is pending the queue waits for it.

Capability: toolApproval

Required scope

Chat.RememberedApproval requires Chat.Root.

Chat.RememberedApproval requires Chat.Parts.

Props

2 documented props · Native <span> attributes supported

Chat.RememberedApproval props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/remembered-approval.tsx

Chat.AlwaysAllowaction · <button>

For a tool declared with needsApproval. PartApproval is the request, with ApprovalReason, Approve, Deny and AlwaysAllow (only with rememberApprovals). Answering calls the SDK's addToolApprovalResponse. ApprovalError says the answer did not reach the server. ApprovalReceipt replaces the controls once answered, RememberedApproval marks a call allowed by a remembered consent, and ForgetApproval takes that consent back. While a decision is pending the queue waits for it.

Capability: toolApproval

Required scope

Chat.AlwaysAllow requires Chat.PartApproval.

Chat.AlwaysAllow requires Chat.Root.

Chat.AlwaysAllow requires Chat.Parts.

Props

2 documented props · Native <button> attributes supported

Chat.AlwaysAllow props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/always-allow.tsx

Chat.ApprovalReceiptcontent · <p>

For a tool declared with needsApproval. PartApproval is the request, with ApprovalReason, Approve, Deny and AlwaysAllow (only with rememberApprovals). Answering calls the SDK's addToolApprovalResponse. ApprovalError says the answer did not reach the server. ApprovalReceipt replaces the controls once answered, RememberedApproval marks a call allowed by a remembered consent, and ForgetApproval takes that consent back. While a decision is pending the queue waits for it.

Capability: toolApproval

Required scope

Chat.ApprovalReceipt requires Chat.Parts.

Props

2 documented props · Native <p> attributes supported

Chat.ApprovalReceipt props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { approved: boolean }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/approval-receipt.tsx

Chat.ApprovalErrorcontent · <p>

For a tool declared with needsApproval. PartApproval is the request, with ApprovalReason, Approve, Deny and AlwaysAllow (only with rememberApprovals). Answering calls the SDK's addToolApprovalResponse. ApprovalError says the answer did not reach the server. ApprovalReceipt replaces the controls once answered, RememberedApproval marks a call allowed by a remembered consent, and ForgetApproval takes that consent back. While a decision is pending the queue waits for it.

Capability: toolApproval

Required scope

Chat.ApprovalError requires Chat.PartApproval.

Chat.ApprovalError requires Chat.Parts.

Props

2 documented props · Native <p> attributes supported

Chat.ApprovalError props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/approval-error.tsx

Chat.ApprovalReasoncontent · <p>

For a tool declared with needsApproval. PartApproval is the request, with ApprovalReason, Approve, Deny and AlwaysAllow (only with rememberApprovals). Answering calls the SDK's addToolApprovalResponse. ApprovalError says the answer did not reach the server. ApprovalReceipt replaces the controls once answered, RememberedApproval marks a call allowed by a remembered consent, and ForgetApproval takes that consent back. While a decision is pending the queue waits for it.

Capability: toolApproval

Required scope

Chat.ApprovalReason requires Chat.Parts.

Props

2 documented props · Native <p> attributes supported

Chat.ApprovalReason props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/approval-reason.tsx

Chat.Denyaction · <button>

For a tool declared with needsApproval. PartApproval is the request, with ApprovalReason, Approve, Deny and AlwaysAllow (only with rememberApprovals). Answering calls the SDK's addToolApprovalResponse. ApprovalError says the answer did not reach the server. ApprovalReceipt replaces the controls once answered, RememberedApproval marks a call allowed by a remembered consent, and ForgetApproval takes that consent back. While a decision is pending the queue waits for it.

Capability: toolApproval

Required scope

Chat.Deny requires Chat.PartApproval.

Props

2 documented props · Native <button> attributes supported

Chat.Deny props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { pending: boolean }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/deny.tsx

Chat.Approveaction · <button>

For a tool declared with needsApproval. PartApproval is the request, with ApprovalReason, Approve, Deny and AlwaysAllow (only with rememberApprovals). Answering calls the SDK's addToolApprovalResponse. ApprovalError says the answer did not reach the server. ApprovalReceipt replaces the controls once answered, RememberedApproval marks a call allowed by a remembered consent, and ForgetApproval takes that consent back. While a decision is pending the queue waits for it.

Capability: toolApproval

Required scope

Chat.Approve requires Chat.PartApproval.

Props

2 documented props · Native <button> attributes supported

Chat.Approve props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { pending: boolean }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/approve.tsx

Chat.PartApprovalcontent · <div>

For a tool declared with needsApproval. PartApproval is the request, with ApprovalReason, Approve, Deny and AlwaysAllow (only with rememberApprovals). Answering calls the SDK's addToolApprovalResponse. ApprovalError says the answer did not reach the server. ApprovalReceipt replaces the controls once answered, RememberedApproval marks a call allowed by a remembered consent, and ForgetApproval takes that consent back. While a decision is pending the queue waits for it.

Capability: toolApproval

Required scope

Chat.PartApproval requires Chat.Parts.

Chat.PartApproval requires Chat.Root.

Props

2 documented props · Native <div> attributes supported

Chat.PartApproval props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/part-approval.tsx

Chat.PartToolgate

One tool call, the SDK's `tool-<name>` or `dynamic-tool` part, wherever it has got to. The state reaches the screen because the seven of them want different things: an input still arriving is a shimmer, an output is a disclosure, a denial is a sentence and an error is a different sentence. One "called a tool" card for all seven would be six lies. `toolName` is the SDK's own reading of the part's type, beside everything the part holds. → docs/rules/capability-honesty.md

Capability: tools

Required scope

Chat.PartTool must be inside <Chat.Parts>.

Props

1 documented props

Chat.PartTool props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: PartToolState) => ReactNode)—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/part-tool.tsx

Chat.QuestionReceiptgate

The askQuestions tool: a form the model asks the person to fill in. PartQuestion is the form, Questions hands the questionnaire, QuestionItem is one fieldset with Answer per choice and OtherAnswer plus QuestionOther for a free answer. ClearAnswer takes an optional pick back. QuestionProgress, QuestionBack and QuestionNext step through several questions, and QuestionInvalid says why Next is refused. SubmitAnswers sends, SkipQuestions writes a skipped output the model reads, QuestionError reports a failed write, and QuestionReceipt takes the form's place once answered.

Capability: tools

Required scope

Chat.QuestionReceipt requires Chat.Parts.

Props

1 documented props

Chat.QuestionReceipt props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: Receipt) => ReactNode)—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/question-receipt.tsx

Chat.QuestionErrorcontent · <p>

The askQuestions tool: a form the model asks the person to fill in. PartQuestion is the form, Questions hands the questionnaire, QuestionItem is one fieldset with Answer per choice and OtherAnswer plus QuestionOther for a free answer. ClearAnswer takes an optional pick back. QuestionProgress, QuestionBack and QuestionNext step through several questions, and QuestionInvalid says why Next is refused. SubmitAnswers sends, SkipQuestions writes a skipped output the model reads, QuestionError reports a failed write, and QuestionReceipt takes the form's place once answered.

Capability: tools

Required scope

Chat.QuestionError requires Chat.PartQuestion.

Props

2 documented props · Native <p> attributes supported

Chat.QuestionError props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/question-error.tsx

Chat.SubmitAnswersaction · <button>

On the last question only: before it, Next is the way on.

Capability: tools

Required scope

Chat.SubmitAnswers requires Chat.PartQuestion.

Props

2 documented props · Native <button> attributes supported

Chat.SubmitAnswers props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/submit-answers.tsx

Chat.SkipQuestionsaction · <button>

Dismisses the open question without answering it. The queue decides what the model hears next: the message the person typed meanwhile, as their reply, or else a nudge to carry on.

Capability: tools

Required scope

Chat.SkipQuestions requires Chat.Root.

Chat.SkipQuestions requires Chat.PartQuestion.

Chat.SkipQuestions requires Chat.Parts.

Props

2 documented props · Native <button> attributes supported

Chat.SkipQuestions props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/skip-questions.tsx

Chat.QuestionOtherinput · <input>

The field of the "Other" row, inline with its control.

Capability: tools

Required scope

Chat.QuestionOther requires Chat.PartQuestion.

Props

3 documented props · Native <input> attributes supported

Chat.QuestionOther props
PropTypeDefault
nameRequired
string—
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/question-other.tsx

Chat.OtherAnswerinput · <input>

The control of the "Other" row, last in the same group as the choices: it replaces the pick of a single question and adds to a multiple one.

Capability: tools

Required scope

Chat.OtherAnswer requires Chat.PartQuestion.

Props

3 documented props · Native <input> attributes supported

Chat.OtherAnswer props
PropTypeDefault
nameRequired
string—
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/other-answer.tsx

Chat.ClearAnsweraction · <button>

Takes a pick back, which a radio cannot do by itself. An optional question only: a required one is changed, not emptied.

Capability: tools

Required scope

Chat.ClearAnswer requires Chat.PartQuestion.

Props

3 documented props · Native <button> attributes supported

Chat.ClearAnswer props
PropTypeDefault
nameRequired
string—
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/clear-answer.tsx

Chat.QuestionProgresscontent · <p>

"2 of 3": the place in a form of several questions, and nothing in a form of one.

Capability: tools

Required scope

Chat.QuestionProgress requires Chat.PartQuestion.

Props

2 documented props · Native <p> attributes supported

Chat.QuestionProgress props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: Progress) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/question-progress.tsx

Chat.QuestionBackaction · <button>

The askQuestions tool: a form the model asks the person to fill in. PartQuestion is the form, Questions hands the questionnaire, QuestionItem is one fieldset with Answer per choice and OtherAnswer plus QuestionOther for a free answer. ClearAnswer takes an optional pick back. QuestionProgress, QuestionBack and QuestionNext step through several questions, and QuestionInvalid says why Next is refused. SubmitAnswers sends, SkipQuestions writes a skipped output the model reads, QuestionError reports a failed write, and QuestionReceipt takes the form's place once answered.

Capability: tools

Required scope

Chat.QuestionBack requires Chat.PartQuestion.

Props

2 documented props · Native <button> attributes supported

Chat.QuestionBack props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/question-back.tsx

Chat.QuestionNextaction · <button>

Goes on once this question's answer is good; the last question has Send answers instead.

Capability: tools

Required scope

Chat.QuestionNext requires Chat.PartQuestion.

Props

2 documented props · Native <button> attributes supported

Chat.QuestionNext props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/question-next.tsx

Chat.QuestionInvalidcontent · <p>

What is missing from one question's answer, once the person tried to go on without it.

Capability: tools

Required scope

Chat.QuestionInvalid requires Chat.PartQuestion.

Props

3 documented props · Native <p> attributes supported

Chat.QuestionInvalid props
PropTypeDefault
nameRequired
string—
children

Content rendered inside this part.

ReactNode | ((state: { problem: QuestionProblem }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/question-invalid.tsx

Chat.Answerinput · <input>

One choice: a radio in a single question and a checkbox in a multiple one, so the kind is plain before anything is touched.

Capability: tools

Required scope

Chat.Answer requires Chat.PartQuestion.

Props

4 documented props · Native <input> attributes supported

Chat.Answer props
PropTypeDefault
nameRequired
string—
valueRequired
string—
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/answer.tsx

Chat.QuestionItemcontent · <fieldset>

One question: a radiogroup when the answer is one choice, a group when it is several. Only the question of the current step is drawn. Number shortcuts stay inside it and never intercept typing.

Capability: tools

Required scope

Chat.QuestionItem requires Chat.PartQuestion.

Props

3 documented props · Native <fieldset> attributes supported

Chat.QuestionItem props
PropTypeDefault
nameRequired
string—
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/question-item.tsx

Chat.Questionsgate

The askQuestions tool: a form the model asks the person to fill in. PartQuestion is the form, Questions hands the questionnaire, QuestionItem is one fieldset with Answer per choice and OtherAnswer plus QuestionOther for a free answer. ClearAnswer takes an optional pick back. QuestionProgress, QuestionBack and QuestionNext step through several questions, and QuestionInvalid says why Next is refused. SubmitAnswers sends, SkipQuestions writes a skipped output the model reads, QuestionError reports a failed write, and QuestionReceipt takes the form's place once answered.

Capability: tools

Required scope

Chat.Questions requires Chat.PartQuestion.

Props

1 documented props

Chat.Questions props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: Questionnaire) => ReactNode)—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/questions.tsx

Chat.PartQuestionaction · <form>

The askQuestions tool: a form the model asks the person to fill in. PartQuestion is the form, Questions hands the questionnaire, QuestionItem is one fieldset with Answer per choice and OtherAnswer plus QuestionOther for a free answer. ClearAnswer takes an optional pick back. QuestionProgress, QuestionBack and QuestionNext step through several questions, and QuestionInvalid says why Next is refused. SubmitAnswers sends, SkipQuestions writes a skipped output the model reads, QuestionError reports a failed write, and QuestionReceipt takes the form's place once answered.

Capability: tools

Required scope

Chat.PartQuestion requires Chat.Parts.

Chat.PartQuestion requires Chat.Root.

Props

2 documented props · Native <form> attributes supported

Chat.PartQuestion props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/part-question.tsx

Chat.CitationRootscope

Sources collects a message's source-url parts. References numbers and deduplicates every source of the message, and PartSource renders the first occurrence of one in place. SourceRoot scopes one source for SourceLink (a validated http(s) link) and SourceUnavailable. CitationRoot and its Trigger, Content, Title and Description are a popover for one citation; SourceSheetRoot and its parts are a modal list of all of them. Nothing renders for an answer without sources, which is most answers from most models.

Capability: sources

Props

1 documented props

Chat.CitationRoot props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/citation-root.tsx

Chat.CitationContentcontent · <div>

The skin's surface preserves the corresponding Motion primitive adapter.

Capability: sources

Required scope

Chat.CitationContent requires Chat.CitationRoot.

Props

2 documented props · Native <div> attributes supported

Chat.CitationContent props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/citation-content.tsx

Chat.CitationTriggeraction · <button>

Sources collects a message's source-url parts. References numbers and deduplicates every source of the message, and PartSource renders the first occurrence of one in place. SourceRoot scopes one source for SourceLink (a validated http(s) link) and SourceUnavailable. CitationRoot and its Trigger, Content, Title and Description are a popover for one citation; SourceSheetRoot and its parts are a modal list of all of them. Nothing renders for an answer without sources, which is most answers from most models.

Capability: sources

Props

2 documented props · Native <button> attributes supported

Chat.CitationTrigger props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/citation-trigger.tsx

Chat.CitationTitlecontent · <h2>

Sources collects a message's source-url parts. References numbers and deduplicates every source of the message, and PartSource renders the first occurrence of one in place. SourceRoot scopes one source for SourceLink (a validated http(s) link) and SourceUnavailable. CitationRoot and its Trigger, Content, Title and Description are a popover for one citation; SourceSheetRoot and its parts are a modal list of all of them. Nothing renders for an answer without sources, which is most answers from most models.

Capability: sources

Props

2 documented props · Native <h2> attributes supported

Chat.CitationTitle props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/citation-title.tsx

Chat.CitationDescriptioncontent · <p>

Sources collects a message's source-url parts. References numbers and deduplicates every source of the message, and PartSource renders the first occurrence of one in place. SourceRoot scopes one source for SourceLink (a validated http(s) link) and SourceUnavailable. CitationRoot and its Trigger, Content, Title and Description are a popover for one citation; SourceSheetRoot and its parts are a modal list of all of them. Nothing renders for an answer without sources, which is most answers from most models.

Capability: sources

Props

2 documented props · Native <p> attributes supported

Chat.CitationDescription props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/citation-description.tsx

Chat.SourceSheetRootscope

Sources collects a message's source-url parts. References numbers and deduplicates every source of the message, and PartSource renders the first occurrence of one in place. SourceRoot scopes one source for SourceLink (a validated http(s) link) and SourceUnavailable. CitationRoot and its Trigger, Content, Title and Description are a popover for one citation; SourceSheetRoot and its parts are a modal list of all of them. Nothing renders for an answer without sources, which is most answers from most models.

Capability: sources

Props

1 documented props

Chat.SourceSheetRoot props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/source-sheet-root.tsx

Chat.SourceSheetContentcontent · <div>

The skin's surface preserves the corresponding Motion primitive adapter.

Capability: sources

Required scope

Chat.SourceSheetContent requires Chat.SourceSheetRoot.

Props

2 documented props · Native <div> attributes supported

Chat.SourceSheetContent props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/source-sheet-content.tsx

Chat.SourceSheetTriggeraction · <button>

Sources collects a message's source-url parts. References numbers and deduplicates every source of the message, and PartSource renders the first occurrence of one in place. SourceRoot scopes one source for SourceLink (a validated http(s) link) and SourceUnavailable. CitationRoot and its Trigger, Content, Title and Description are a popover for one citation; SourceSheetRoot and its parts are a modal list of all of them. Nothing renders for an answer without sources, which is most answers from most models.

Capability: sources

Props

2 documented props · Native <button> attributes supported

Chat.SourceSheetTrigger props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/source-sheet-trigger.tsx

Chat.SourceSheetTitlecontent · <h2>

Sources collects a message's source-url parts. References numbers and deduplicates every source of the message, and PartSource renders the first occurrence of one in place. SourceRoot scopes one source for SourceLink (a validated http(s) link) and SourceUnavailable. CitationRoot and its Trigger, Content, Title and Description are a popover for one citation; SourceSheetRoot and its parts are a modal list of all of them. Nothing renders for an answer without sources, which is most answers from most models.

Capability: sources

Props

2 documented props · Native <h2> attributes supported

Chat.SourceSheetTitle props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/source-sheet-title.tsx

Chat.SourceSheetDescriptioncontent · <p>

Sources collects a message's source-url parts. References numbers and deduplicates every source of the message, and PartSource renders the first occurrence of one in place. SourceRoot scopes one source for SourceLink (a validated http(s) link) and SourceUnavailable. CitationRoot and its Trigger, Content, Title and Description are a popover for one citation; SourceSheetRoot and its parts are a modal list of all of them. Nothing renders for an answer without sources, which is most answers from most models.

Capability: sources

Props

2 documented props · Native <p> attributes supported

Chat.SourceSheetDescription props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/source-sheet-description.tsx

Chat.SourceSheetCloseaction · <button>

Sources collects a message's source-url parts. References numbers and deduplicates every source of the message, and PartSource renders the first occurrence of one in place. SourceRoot scopes one source for SourceLink (a validated http(s) link) and SourceUnavailable. CitationRoot and its Trigger, Content, Title and Description are a popover for one citation; SourceSheetRoot and its parts are a modal list of all of them. Nothing renders for an answer without sources, which is most answers from most models.

Capability: sources

Props

2 documented props · Native <button> attributes supported

Chat.SourceSheetClose props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/source-sheet-close.tsx

Chat.Referencesgate

URL and document references in native transcript order, deduplicated by source identity.

Capability: sources

Required scope

Chat.References requires Chat.Messages.

Props

1 documented props

Chat.References props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { sources: readonly ChatSource[] }) => ReactNode)—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/references.tsx

Chat.PartSourcegate

Sources collects a message's source-url parts. References numbers and deduplicates every source of the message, and PartSource renders the first occurrence of one in place. SourceRoot scopes one source for SourceLink (a validated http(s) link) and SourceUnavailable. CitationRoot and its Trigger, Content, Title and Description are a popover for one citation; SourceSheetRoot and its parts are a modal list of all of them. Nothing renders for an answer without sources, which is most answers from most models.

Capability: sources

Required scope

Chat.PartSource requires Chat.Messages.

Chat.PartSource requires Chat.Parts.

Props

1 documented props

Chat.PartSource props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { source: ChatSource }) => ReactNode)—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/part-source.tsx

Chat.SourceRootscope

Sources collects a message's source-url parts. References numbers and deduplicates every source of the message, and PartSource renders the first occurrence of one in place. SourceRoot scopes one source for SourceLink (a validated http(s) link) and SourceUnavailable. CitationRoot and its Trigger, Content, Title and Description are a popover for one citation; SourceSheetRoot and its parts are a modal list of all of them. Nothing renders for an answer without sources, which is most answers from most models.

Capability: sources

Props

2 documented props

Chat.SourceRoot props
PropTypeDefault
sourceRequired
ChatSource—
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/source-root.tsx

Chat.SourceUnavailablegate

Sources collects a message's source-url parts. References numbers and deduplicates every source of the message, and PartSource renders the first occurrence of one in place. SourceRoot scopes one source for SourceLink (a validated http(s) link) and SourceUnavailable. CitationRoot and its Trigger, Content, Title and Description are a popover for one citation; SourceSheetRoot and its parts are a modal list of all of them. Nothing renders for an answer without sources, which is most answers from most models.

Capability: sources

Required scope

Chat.SourceUnavailable requires Chat.SourceRoot.

Props

1 documented props

Chat.SourceUnavailable props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/source-unavailable.tsx

Chat.Sourcesgate

What the answer was drawn from, the SDK's `source-url` parts, collected. A footer rather than a part in the flow: citations arrive interleaved with the prose and read as an appendix, and a reader who wants them wants all of them at once. A document source has no URL to open, and a citation nobody can follow is a row that looks like a link and is not one. Nothing is rendered where the backend sent none, which is most backends.

Capability: sources

Required scope

Chat.Sources must be inside <Chat.Messages>.

Props

1 documented props

Chat.Sources props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { sources: SourceUrlUIPart[] }) => ReactNode)—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/sources.tsx

Chat.FileRootscope

PartFile gates a file part. FileRoot validates one FileUIPart and owns its load error. FileKind gates by media kind, FileImage, FileAudio and FileVideo render the media with the source locked, FileLink is an http(s) link only, and FileUnavailable covers a bad source or a failed load. These parts display files the conversation already holds. Sending files is Composer's attachments field, and grouped previews are the chat-media parts.

Capability: files

Props

2 documented props

Chat.FileRoot props
PropTypeDefault
fileRequired
FileUIPart—
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/file-root.tsx

Chat.FileKindgate

PartFile gates a file part. FileRoot validates one FileUIPart and owns its load error. FileKind gates by media kind, FileImage, FileAudio and FileVideo render the media with the source locked, FileLink is an http(s) link only, and FileUnavailable covers a bad source or a failed load. These parts display files the conversation already holds. Sending files is Composer's attachments field, and grouped previews are the chat-media parts.

Capability: files

Required scope

Chat.FileKind requires Chat.FileRoot.

Props

2 documented props

Chat.FileKind props
PropTypeDefault
kindRequired
"image" | "audio" | "video" | "file"—
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/file-kind-gate.tsx

Chat.FileImagecontent · <img>

PartFile gates a file part. FileRoot validates one FileUIPart and owns its load error. FileKind gates by media kind, FileImage, FileAudio and FileVideo render the media with the source locked, FileLink is an http(s) link only, and FileUnavailable covers a bad source or a failed load. These parts display files the conversation already holds. Sending files is Composer's attachments field, and grouped previews are the chat-media parts.

Capability: files

Required scope

Chat.FileImage requires Chat.FileRoot.

File media requires Chat.FileRoot.

Props

2 documented props · Native <img> attributes supported

Chat.FileImage props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/file-img.tsx

Chat.FileAudiocontent · <audio>

PartFile gates a file part. FileRoot validates one FileUIPart and owns its load error. FileKind gates by media kind, FileImage, FileAudio and FileVideo render the media with the source locked, FileLink is an http(s) link only, and FileUnavailable covers a bad source or a failed load. These parts display files the conversation already holds. Sending files is Composer's attachments field, and grouped previews are the chat-media parts.

Capability: files

Required scope

Chat.FileAudio requires Chat.FileRoot.

File media requires Chat.FileRoot.

Props

2 documented props · Native <audio> attributes supported

Chat.FileAudio props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/file-audio.tsx

Chat.FileVideocontent · <video>

PartFile gates a file part. FileRoot validates one FileUIPart and owns its load error. FileKind gates by media kind, FileImage, FileAudio and FileVideo render the media with the source locked, FileLink is an http(s) link only, and FileUnavailable covers a bad source or a failed load. These parts display files the conversation already holds. Sending files is Composer's attachments field, and grouped previews are the chat-media parts.

Capability: files

Required scope

Chat.FileVideo requires Chat.FileRoot.

File media requires Chat.FileRoot.

Props

2 documented props · Native <video> attributes supported

Chat.FileVideo props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/file-video.tsx

Chat.FileUnavailablegate

PartFile gates a file part. FileRoot validates one FileUIPart and owns its load error. FileKind gates by media kind, FileImage, FileAudio and FileVideo render the media with the source locked, FileLink is an http(s) link only, and FileUnavailable covers a bad source or a failed load. These parts display files the conversation already holds. Sending files is Composer's attachments field, and grouped previews are the chat-media parts.

Capability: files

Required scope

Chat.FileUnavailable requires Chat.FileRoot.

Props

1 documented props

Chat.FileUnavailable props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/file-unavailable.tsx

Chat.PartFilegate

A native file stays visible in history even when the rich media viewer is not installed.

Capability: files

Required scope

Chat.PartFile requires Chat.Parts.

Props

1 documented props

Chat.PartFile props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { file: FileUIPart }) => ReactNode)—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/part-file.tsx

Chat.EditedAttachmentsgate

BranchNavigation, BranchPrevious, BranchNext and BranchPage ({ index, total }) step through the alternatives Regenerate and edits create. MessageEditRoot wraps a message's content, and MessageReading and MessageEditing gate the two modes. Edit opens the editor. Editing a sent message is chat behaviour, so the editor stays a chat part: in v2 MessageEditor provides its own sink (whenBusy "hold", submit creates a branch) and renders a Composer with the message's text as defaultValue. EditedInput and SaveEdit map to Composer.Input and Composer.Submit inside it. EditedAttachments exposes the files the edited message keeps, and CancelEdit leaves history unchanged.

Required scope

Chat.EditedAttachments requires Chat.Messages.

Props

1 documented props

Chat.EditedAttachments props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { files: readonly FileUIPart[] }) => ReactNode)—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/edited-attachments.tsx

Chat.BranchNavigationgate

BranchNavigation, BranchPrevious, BranchNext and BranchPage ({ index, total }) step through the alternatives Regenerate and edits create. MessageEditRoot wraps a message's content, and MessageReading and MessageEditing gate the two modes. Edit opens the editor. Editing a sent message is chat behaviour, so the editor stays a chat part: in v2 MessageEditor provides its own sink (whenBusy "hold", submit creates a branch) and renders a Composer with the message's text as defaultValue. EditedInput and SaveEdit map to Composer.Input and Composer.Submit inside it. EditedAttachments exposes the files the edited message keeps, and CancelEdit leaves history unchanged.

Required scope

Chat.BranchNavigation requires Chat.Root.

Chat.BranchNavigation requires Chat.Messages.

Props

1 documented props

Chat.BranchNavigation props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/branch-navigation.tsx

Chat.BranchPreviousaction · <button>

BranchNavigation, BranchPrevious, BranchNext and BranchPage ({ index, total }) step through the alternatives Regenerate and edits create. MessageEditRoot wraps a message's content, and MessageReading and MessageEditing gate the two modes. Edit opens the editor. Editing a sent message is chat behaviour, so the editor stays a chat part: in v2 MessageEditor provides its own sink (whenBusy "hold", submit creates a branch) and renders a Composer with the message's text as defaultValue. EditedInput and SaveEdit map to Composer.Input and Composer.Submit inside it. EditedAttachments exposes the files the edited message keeps, and CancelEdit leaves history unchanged.

Required scope

Chat.BranchPrevious requires Chat.Root.

Chat.BranchPrevious requires Chat.Messages.

Props

2 documented props · Native <button> attributes supported

Chat.BranchPrevious props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/branch-previous.tsx

Chat.BranchNextaction · <button>

BranchNavigation, BranchPrevious, BranchNext and BranchPage ({ index, total }) step through the alternatives Regenerate and edits create. MessageEditRoot wraps a message's content, and MessageReading and MessageEditing gate the two modes. Edit opens the editor. Editing a sent message is chat behaviour, so the editor stays a chat part: in v2 MessageEditor provides its own sink (whenBusy "hold", submit creates a branch) and renders a Composer with the message's text as defaultValue. EditedInput and SaveEdit map to Composer.Input and Composer.Submit inside it. EditedAttachments exposes the files the edited message keeps, and CancelEdit leaves history unchanged.

Required scope

Chat.BranchNext requires Chat.Root.

Chat.BranchNext requires Chat.Messages.

Props

2 documented props · Native <button> attributes supported

Chat.BranchNext props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/branch-next.tsx

Chat.BranchPagecontent · <span>

BranchNavigation, BranchPrevious, BranchNext and BranchPage ({ index, total }) step through the alternatives Regenerate and edits create. MessageEditRoot wraps a message's content, and MessageReading and MessageEditing gate the two modes. Edit opens the editor. Editing a sent message is chat behaviour, so the editor stays a chat part: in v2 MessageEditor provides its own sink (whenBusy "hold", submit creates a branch) and renders a Composer with the message's text as defaultValue. EditedInput and SaveEdit map to Composer.Input and Composer.Submit inside it. EditedAttachments exposes the files the edited message keeps, and CancelEdit leaves history unchanged.

Required scope

Chat.BranchPage requires Chat.Root.

Chat.BranchPage requires Chat.Messages.

Props

2 documented props · Native <span> attributes supported

Chat.BranchPage props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { index: number; total: number }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/branch-page.tsx

Chat.MessageEditRootscope

BranchNavigation, BranchPrevious, BranchNext and BranchPage ({ index, total }) step through the alternatives Regenerate and edits create. MessageEditRoot wraps a message's content, and MessageReading and MessageEditing gate the two modes. Edit opens the editor. Editing a sent message is chat behaviour, so the editor stays a chat part: in v2 MessageEditor provides its own sink (whenBusy "hold", submit creates a branch) and renders a Composer with the message's text as defaultValue. EditedInput and SaveEdit map to Composer.Input and Composer.Submit inside it. EditedAttachments exposes the files the edited message keeps, and CancelEdit leaves history unchanged.

Required scope

Chat.MessageEditRoot requires Chat.Messages.

Props

1 documented props

Chat.MessageEditRoot props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/message-edit-root.tsx

Chat.MessageEditinggate

BranchNavigation, BranchPrevious, BranchNext and BranchPage ({ index, total }) step through the alternatives Regenerate and edits create. MessageEditRoot wraps a message's content, and MessageReading and MessageEditing gate the two modes. Edit opens the editor. Editing a sent message is chat behaviour, so the editor stays a chat part: in v2 MessageEditor provides its own sink (whenBusy "hold", submit creates a branch) and renders a Composer with the message's text as defaultValue. EditedInput and SaveEdit map to Composer.Input and Composer.Submit inside it. EditedAttachments exposes the files the edited message keeps, and CancelEdit leaves history unchanged.

Required scope

Chat.MessageEditing requires Chat.MessageEditRoot.

Props

1 documented props

Chat.MessageEditing props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/message-editing.tsx

Chat.MessageReadinggate

BranchNavigation, BranchPrevious, BranchNext and BranchPage ({ index, total }) step through the alternatives Regenerate and edits create. MessageEditRoot wraps a message's content, and MessageReading and MessageEditing gate the two modes. Edit opens the editor. Editing a sent message is chat behaviour, so the editor stays a chat part: in v2 MessageEditor provides its own sink (whenBusy "hold", submit creates a branch) and renders a Composer with the message's text as defaultValue. EditedInput and SaveEdit map to Composer.Input and Composer.Submit inside it. EditedAttachments exposes the files the edited message keeps, and CancelEdit leaves history unchanged.

Required scope

Chat.MessageReading requires Chat.MessageEditRoot.

Props

1 documented props

Chat.MessageReading props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/message-reading.tsx

Chat.Editaction · <button>

BranchNavigation, BranchPrevious, BranchNext and BranchPage ({ index, total }) step through the alternatives Regenerate and edits create. MessageEditRoot wraps a message's content, and MessageReading and MessageEditing gate the two modes. Edit opens the editor. Editing a sent message is chat behaviour, so the editor stays a chat part: in v2 MessageEditor provides its own sink (whenBusy "hold", submit creates a branch) and renders a Composer with the message's text as defaultValue. EditedInput and SaveEdit map to Composer.Input and Composer.Submit inside it. EditedAttachments exposes the files the edited message keeps, and CancelEdit leaves history unchanged.

Required scope

Chat.Edit requires Chat.Root.

Chat.Edit requires Chat.Messages.

Chat.Edit requires Chat.MessageEditRoot.

Props

2 documented props · Native <button> attributes supported

Chat.Edit props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/edit.tsx

Chat.MessageEditoraction · <form>

BranchNavigation, BranchPrevious, BranchNext and BranchPage ({ index, total }) step through the alternatives Regenerate and edits create. MessageEditRoot wraps a message's content, and MessageReading and MessageEditing gate the two modes. Edit opens the editor. Editing a sent message is chat behaviour, so the editor stays a chat part: in v2 MessageEditor provides its own sink (whenBusy "hold", submit creates a branch) and renders a Composer with the message's text as defaultValue. EditedInput and SaveEdit map to Composer.Input and Composer.Submit inside it. EditedAttachments exposes the files the edited message keeps, and CancelEdit leaves history unchanged.

Required scope

Chat.MessageEditor requires Chat.Root.

Chat.MessageEditor requires Chat.Messages.

Chat.MessageEditor requires Chat.MessageEditRoot.

Props

2 documented props · Native <form> attributes supported

Chat.MessageEditor props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/message-editor.tsx

Chat.EditedInputinput · <textarea>

BranchNavigation, BranchPrevious, BranchNext and BranchPage ({ index, total }) step through the alternatives Regenerate and edits create. MessageEditRoot wraps a message's content, and MessageReading and MessageEditing gate the two modes. Edit opens the editor. Editing a sent message is chat behaviour, so the editor stays a chat part: in v2 MessageEditor provides its own sink (whenBusy "hold", submit creates a branch) and renders a Composer with the message's text as defaultValue. EditedInput and SaveEdit map to Composer.Input and Composer.Submit inside it. EditedAttachments exposes the files the edited message keeps, and CancelEdit leaves history unchanged.

Required scope

Chat.EditedInput requires Chat.Root.

Chat.EditedInput requires Chat.MessageEditRoot.

Props

2 documented props · Native <textarea> attributes supported

Chat.EditedInput props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/edited-input.tsx

Chat.CancelEditaction · <button>

BranchNavigation, BranchPrevious, BranchNext and BranchPage ({ index, total }) step through the alternatives Regenerate and edits create. MessageEditRoot wraps a message's content, and MessageReading and MessageEditing gate the two modes. Edit opens the editor. Editing a sent message is chat behaviour, so the editor stays a chat part: in v2 MessageEditor provides its own sink (whenBusy "hold", submit creates a branch) and renders a Composer with the message's text as defaultValue. EditedInput and SaveEdit map to Composer.Input and Composer.Submit inside it. EditedAttachments exposes the files the edited message keeps, and CancelEdit leaves history unchanged.

Required scope

Chat.CancelEdit requires Chat.MessageEditRoot.

Props

2 documented props · Native <button> attributes supported

Chat.CancelEdit props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/cancel-edit.tsx

Chat.SaveEditaction · <button>

BranchNavigation, BranchPrevious, BranchNext and BranchPage ({ index, total }) step through the alternatives Regenerate and edits create. MessageEditRoot wraps a message's content, and MessageReading and MessageEditing gate the two modes. Edit opens the editor. Editing a sent message is chat behaviour, so the editor stays a chat part: in v2 MessageEditor provides its own sink (whenBusy "hold", submit creates a branch) and renders a Composer with the message's text as defaultValue. EditedInput and SaveEdit map to Composer.Input and Composer.Submit inside it. EditedAttachments exposes the files the edited message keeps, and CancelEdit leaves history unchanged.

Required scope

Chat.SaveEdit requires Chat.Root.

Chat.SaveEdit requires Chat.Messages.

Chat.SaveEdit requires Chat.MessageEditRoot.

Props

2 documented props · Native <button> attributes supported

Chat.SaveEdit props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/save-edit.tsx

Chat.MessageFootercontent · <div>

Completed-turn actions stay available on the latest answer and to keyboard/touch readers.

Required scope

Chat.MessageFooter must be inside <Chat.Messages>.

Chat.MessageFooter must be inside <Chat.Root>.

Props

2 documented props · Native <div> attributes supported

Chat.MessageFooter props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/message-footer.tsx

Chat.Copyaction · <button>

Puts this message's text on the clipboard, and says so. The text and nothing else: a reader copying an answer wants the answer, not the reasoning trace above it or the JSON of a tool call beside it. Runs of prose a tool call separated stay separate paragraphs.

Required scope

Chat.Copy must be inside <Chat.Messages>.

Props

2 documented props · Native <button> attributes supported

Chat.Copy props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { copied: boolean }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/copy.tsx

Chat.FeedbackRootscope

MessageFooter holds a turn's actions and is data-active on the latest answer. Copy puts the text parts on the clipboard. ReadAloud speaks the answer. Regenerate renders only on the last assistant message. FeedbackRoot, Feedback rating="up" or "down" and FeedbackError call onFeedback and render nothing without it.

Required scope

Chat.FeedbackRoot requires Chat.Root.

Chat.FeedbackRoot requires Chat.Messages.

Props

1 documented props

Chat.FeedbackRoot props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/feedback-root.tsx

Chat.Feedbackaction · <button>

MessageFooter holds a turn's actions and is data-active on the latest answer. Copy puts the text parts on the clipboard. ReadAloud speaks the answer. Regenerate renders only on the last assistant message. FeedbackRoot, Feedback rating="up" or "down" and FeedbackError call onFeedback and render nothing without it.

Required scope

Chat.Feedback requires Chat.FeedbackRoot.

Props

3 documented props · Native <button> attributes supported

Chat.Feedback props
PropTypeDefault
ratingRequired
"up" | "down"—
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/feedback.tsx

Chat.FeedbackErrorgate

MessageFooter holds a turn's actions and is data-active on the latest answer. Copy puts the text parts on the clipboard. ReadAloud speaks the answer. Regenerate renders only on the last assistant message. FeedbackRoot, Feedback rating="up" or "down" and FeedbackError call onFeedback and render nothing without it.

Required scope

Chat.FeedbackError requires Chat.FeedbackRoot.

Props

1 documented props

Chat.FeedbackError props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/feedback-error.tsx

Chat.ReadAloudaction · <button>

MessageFooter holds a turn's actions and is data-active on the latest answer. Copy puts the text parts on the clipboard. ReadAloud speaks the answer. Regenerate renders only on the last assistant message. FeedbackRoot, Feedback rating="up" or "down" and FeedbackError call onFeedback and render nothing without it.

Required scope

Chat.ReadAloud requires Chat.Messages.

Props

2 documented props · Native <button> attributes supported

Chat.ReadAloud props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { playing: boolean; failed: boolean }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/read-aloud.tsx

Chat.Regenerateaction · <button>

An older answer is safe to regenerate once its entire tail is preserved as a branch.

Required scope

Chat.Regenerate requires Chat.Root.

Chat.Regenerate requires Chat.Messages.

Props

2 documented props · Native <button> attributes supported

Chat.Regenerate props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/regenerate.tsx

Chat.ToggleToolaction · <button>

Settings gates a toolbar that exists only when the config publishes a catalog. Models hands the models on offer and ModelPicker is a native select. OptionalTools hands the catalog, or with selected the active subset, and ToggleTool tool={id} is a pressed/unpressed button. Choices belong to this conversation and the server checks every one.

Required scope

Chat.ToggleTool requires Chat.Root.

Props

3 documented props · Native <button> attributes supported

Chat.ToggleTool props
PropTypeDefault
toolRequired
string—
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/toggle-tool.tsx

Chat.OptionalToolsgate

Settings gates a toolbar that exists only when the config publishes a catalog. Models hands the models on offer and ModelPicker is a native select. OptionalTools hands the catalog, or with selected the active subset, and ToggleTool tool={id} is a pressed/unpressed button. Choices belong to this conversation and the server checks every one.

Required scope

Chat.OptionalTools requires Chat.Root.

Props

2 documented props

Chat.OptionalTools props
PropTypeDefault
selected
booleanfalse
children

Content rendered inside this part.

ReactNode | ((state: { tools: NonNullable<ChatChoices["tools"]> }) => ReactNode)—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/optional-tools.tsx

Chat.ModelPickerinput · <select>

Settings gates a toolbar that exists only when the config publishes a catalog. Models hands the models on offer and ModelPicker is a native select. OptionalTools hands the catalog, or with selected the active subset, and ToggleTool tool={id} is a pressed/unpressed button. Choices belong to this conversation and the server checks every one.

Required scope

Chat.ModelPicker requires Chat.Root.

Props

2 documented props · Native <select> attributes supported

Chat.ModelPicker props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/model-picker.tsx

Chat.Modelsgate

Settings gates a toolbar that exists only when the config publishes a catalog. Models hands the models on offer and ModelPicker is a native select. OptionalTools hands the catalog, or with selected the active subset, and ToggleTool tool={id} is a pressed/unpressed button. Choices belong to this conversation and the server checks every one.

Required scope

Chat.Models requires Chat.Root.

Props

1 documented props

Chat.Models props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { models: NonNullable<ChatChoices["models"]> }) => ReactNode)—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/models.tsx

Chat.Settingsgate

Settings gates a toolbar that exists only when the config publishes a catalog. Models hands the models on offer and ModelPicker is a native select. OptionalTools hands the catalog, or with selected the active subset, and ToggleTool tool={id} is a pressed/unpressed button. Choices belong to this conversation and the server checks every one.

Required scope

Chat.Settings requires Chat.Root.

Props

1 documented props

Chat.Settings props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/settings.tsx

Chat.SendNowaction · <button>

The queue belongs to the sink: with whenBusy "queue", Chat.Root accepts a message while a reply streams and holds it until the chat is ready. These parts show it. Queued hands { count, waitingFor } where waitingFor is "turn", "question" or "approval", and belongs inside a region mounted from the first render. QueueItems repeats the waiting messages, QueueItem is one, QueuePreview shows its text and files. EditQueued opens QueueEditing with QueuedInput, SaveQueued and CancelQueueEdit. CancelQueued drops one. SendNow stops the running answer and sends this one first; with a question open, it skips the question and sends the message as the reply.

Required scope

Chat.SendNow requires Chat.Root.

Chat.SendNow requires Chat.QueueItems.

Props

2 documented props · Native <button> attributes supported

Chat.SendNow props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/send-now.tsx

Chat.CancelQueuedaction · <button>

The queue belongs to the sink: with whenBusy "queue", Chat.Root accepts a message while a reply streams and holds it until the chat is ready. These parts show it. Queued hands { count, waitingFor } where waitingFor is "turn", "question" or "approval", and belongs inside a region mounted from the first render. QueueItems repeats the waiting messages, QueueItem is one, QueuePreview shows its text and files. EditQueued opens QueueEditing with QueuedInput, SaveQueued and CancelQueueEdit. CancelQueued drops one. SendNow stops the running answer and sends this one first; with a question open, it skips the question and sends the message as the reply.

Required scope

Chat.CancelQueued requires Chat.Root.

Chat.CancelQueued requires Chat.QueueItems.

Props

2 documented props · Native <button> attributes supported

Chat.CancelQueued props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/cancel-queued.tsx

Chat.CancelQueueEditaction · <button>

The queue belongs to the sink: with whenBusy "queue", Chat.Root accepts a message while a reply streams and holds it until the chat is ready. These parts show it. Queued hands { count, waitingFor } where waitingFor is "turn", "question" or "approval", and belongs inside a region mounted from the first render. QueueItems repeats the waiting messages, QueueItem is one, QueuePreview shows its text and files. EditQueued opens QueueEditing with QueuedInput, SaveQueued and CancelQueueEdit. CancelQueued drops one. SendNow stops the running answer and sends this one first; with a question open, it skips the question and sends the message as the reply.

Required scope

Chat.CancelQueueEdit requires Chat.Root.

Chat.CancelQueueEdit requires Chat.QueueItems.

Props

2 documented props · Native <button> attributes supported

Chat.CancelQueueEdit props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/cancel-queue-edit.tsx

Chat.SaveQueuedaction · <button>

The queue belongs to the sink: with whenBusy "queue", Chat.Root accepts a message while a reply streams and holds it until the chat is ready. These parts show it. Queued hands { count, waitingFor } where waitingFor is "turn", "question" or "approval", and belongs inside a region mounted from the first render. QueueItems repeats the waiting messages, QueueItem is one, QueuePreview shows its text and files. EditQueued opens QueueEditing with QueuedInput, SaveQueued and CancelQueueEdit. CancelQueued drops one. SendNow stops the running answer and sends this one first; with a question open, it skips the question and sends the message as the reply.

Required scope

Chat.SaveQueued requires Chat.Root.

Chat.SaveQueued requires Chat.QueueItems.

Props

2 documented props · Native <button> attributes supported

Chat.SaveQueued props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/save-queued.tsx

Chat.EditQueuedaction · <button>

The queue belongs to the sink: with whenBusy "queue", Chat.Root accepts a message while a reply streams and holds it until the chat is ready. These parts show it. Queued hands { count, waitingFor } where waitingFor is "turn", "question" or "approval", and belongs inside a region mounted from the first render. QueueItems repeats the waiting messages, QueueItem is one, QueuePreview shows its text and files. EditQueued opens QueueEditing with QueuedInput, SaveQueued and CancelQueueEdit. CancelQueued drops one. SendNow stops the running answer and sends this one first; with a question open, it skips the question and sends the message as the reply.

Required scope

Chat.EditQueued requires Chat.Root.

Chat.EditQueued requires Chat.QueueItems.

Props

2 documented props · Native <button> attributes supported

Chat.EditQueued props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/edit-queued.tsx

Chat.QueuedInputinput · <textarea>

The queue belongs to the sink: with whenBusy "queue", Chat.Root accepts a message while a reply streams and holds it until the chat is ready. These parts show it. Queued hands { count, waitingFor } where waitingFor is "turn", "question" or "approval", and belongs inside a region mounted from the first render. QueueItems repeats the waiting messages, QueueItem is one, QueuePreview shows its text and files. EditQueued opens QueueEditing with QueuedInput, SaveQueued and CancelQueueEdit. CancelQueued drops one. SendNow stops the running answer and sends this one first; with a question open, it skips the question and sends the message as the reply.

Required scope

Chat.QueuedInput requires Chat.Root.

Chat.QueuedInput requires Chat.QueueItems.

Props

2 documented props · Native <textarea> attributes supported

Chat.QueuedInput props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/queued-input.tsx

Chat.QueueEditinggate

The queue belongs to the sink: with whenBusy "queue", Chat.Root accepts a message while a reply streams and holds it until the chat is ready. These parts show it. Queued hands { count, waitingFor } where waitingFor is "turn", "question" or "approval", and belongs inside a region mounted from the first render. QueueItems repeats the waiting messages, QueueItem is one, QueuePreview shows its text and files. EditQueued opens QueueEditing with QueuedInput, SaveQueued and CancelQueueEdit. CancelQueued drops one. SendNow stops the running answer and sends this one first; with a question open, it skips the question and sends the message as the reply.

Required scope

Chat.QueueEditing requires Chat.QueueItems.

Props

1 documented props

Chat.QueueEditing props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { text: string }) => ReactNode)—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/queue-editing.tsx

Chat.QueuePreviewgate

The queue belongs to the sink: with whenBusy "queue", Chat.Root accepts a message while a reply streams and holds it until the chat is ready. These parts show it. Queued hands { count, waitingFor } where waitingFor is "turn", "question" or "approval", and belongs inside a region mounted from the first render. QueueItems repeats the waiting messages, QueueItem is one, QueuePreview shows its text and files. EditQueued opens QueueEditing with QueuedInput, SaveQueued and CancelQueueEdit. CancelQueued drops one. SendNow stops the running answer and sends this one first; with a question open, it skips the question and sends the message as the reply.

Required scope

Chat.QueuePreview requires Chat.QueueItems.

Props

1 documented props

Chat.QueuePreview props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { text: string; files: readonly FileUIPart[] }) => ReactNode)—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/queue-preview.tsx

Chat.QueueItemcontent · <div>

The queue belongs to the sink: with whenBusy "queue", Chat.Root accepts a message while a reply streams and holds it until the chat is ready. These parts show it. Queued hands { count, waitingFor } where waitingFor is "turn", "question" or "approval", and belongs inside a region mounted from the first render. QueueItems repeats the waiting messages, QueueItem is one, QueuePreview shows its text and files. EditQueued opens QueueEditing with QueuedInput, SaveQueued and CancelQueueEdit. CancelQueued drops one. SendNow stops the running answer and sends this one first; with a question open, it skips the question and sends the message as the reply.

Required scope

Chat.QueueItem requires Chat.QueueItems.

Props

2 documented props · Native <div> attributes supported

Chat.QueueItem props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/queue-item.tsx

Chat.QueueItemsscope

The queue belongs to the sink: with whenBusy "queue", Chat.Root accepts a message while a reply streams and holds it until the chat is ready. These parts show it. Queued hands { count, waitingFor } where waitingFor is "turn", "question" or "approval", and belongs inside a region mounted from the first render. QueueItems repeats the waiting messages, QueueItem is one, QueuePreview shows its text and files. EditQueued opens QueueEditing with QueuedInput, SaveQueued and CancelQueueEdit. CancelQueued drops one. SendNow stops the running answer and sends this one first; with a question open, it skips the question and sends the message as the reply.

Required scope

Chat.QueueItems requires Chat.Root.

Props

1 documented props

Chat.QueueItems props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/queue-items.tsx

Chat.Queuedgate

How many messages are waiting, and for what: the running turn, an open question or a tool decision. A reason is always given, because a queue that holds without saying why looks broken. The queue was computed, returned and thrown away, so typing during an answer cleared the box and showed nothing: three follow-ups looked like three sends that did not work, and then arrived minutes later in an order nobody could predict. This is a gate and not a live region, and the difference matters: a region announces what appears *inside* it, so one that arrives already holding its sentence announces nothing. The region is the composer's, mounted from the first render; this puts a sentence into it.

Required scope

Chat.Queued must be inside <Chat.Root>.

Props

1 documented props

Chat.Queued props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { count: number; waitingFor: "turn" | "question" | "approval" }) => ReactNode)—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/queued.tsx

ChatMedia.Rootscope

Root scopes one message and registers its media with Quick Look, so previous and next move through this message's files. ImageRun gates a run of consecutive images and hands { images, remaining }. More count={n} renders only when a run holds more images than are drawn, for a +N tile that opens the rest. OtherFile gates any other file and hands { file, id } so it keeps its name and media type, with a native player for audio and video.

Required scope

ChatMedia.Root requires Chat.Messages.

Props

1 documented props

ChatMedia.Root props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/chat-media/src/headless/root.tsx

ChatMedia.ImageRungate

Root scopes one message and registers its media with Quick Look, so previous and next move through this message's files. ImageRun gates a run of consecutive images and hands { images, remaining }. More count={n} renders only when a run holds more images than are drawn, for a +N tile that opens the rest. OtherFile gates any other file and hands { file, id } so it keeps its name and media type, with a native player for audio and video.

Required scope

ChatMedia.ImageRun requires Chat.Messages.

ChatMedia.ImageRun requires Chat.Parts.

Props

1 documented props

ChatMedia.ImageRun props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: ChatImageRun) => ReactNode)—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/chat-media/src/headless/image-run.tsx

ChatMedia.OtherFilegate

Root scopes one message and registers its media with Quick Look, so previous and next move through this message's files. ImageRun gates a run of consecutive images and hands { images, remaining }. More count={n} renders only when a run holds more images than are drawn, for a +N tile that opens the rest. OtherFile gates any other file and hands { file, id } so it keeps its name and media type, with a native player for audio and video.

Required scope

ChatMedia.OtherFile requires Chat.Messages.

ChatMedia.OtherFile requires Chat.Parts.

Props

1 documented props

ChatMedia.OtherFile props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { file: FileUIPart; id: string }) => ReactNode)—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/chat-media/src/headless/other-file.tsx

ChatMedia.Moregate

Root scopes one message and registers its media with Quick Look, so previous and next move through this message's files. ImageRun gates a run of consecutive images and hands { images, remaining }. More count={n} renders only when a run holds more images than are drawn, for a +N tile that opens the rest. OtherFile gates any other file and hands { file, id } so it keeps its name and media type, with a native player for audio and video.

Props

2 documented props

ChatMedia.More props
PropTypeDefault
countRequired
number—
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/chat-media/src/headless/more.tsx

Markdowncontent · Generic

Model output as markdown, safely, while it is still arriving. Two of these are not things to write by hand, which is why there is a dependency here at all. Completing half-streamed markdown: a fence, a bold run or a link that the next token will finish must render as what it is becoming, or every answer flickers through its own source. And sanitising: this text came from a model that reads the web, so a link is untrusted input and an `<img onerror>` is a real thing to receive — the renderer hardens the tree and this narrows what a URL may start with. Nothing here is styled: the caller's `components` and `className` are the looks, so there is no stylesheet to import and no class that Tailwind was never shown.

Props

7 documented props

Markdown props
PropTypeDefault
extensions
readonly ("math" | "diagrams")[]—
labelsRequired
MarkdownLabels—
className
string—
streaming
booleanfalse
components
MarkdownComponents—
cursor

Shown after the text while it is still arriving; it is decoration, so it is hidden from a screen reader.

ReactElement<ComponentProps<"span">>—
childrenRequired
string—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/markdown/src/markdown-view.tsx

ChatAttachments.Rootscope

Missing storage leaves a fully functional text composer with no attachment controls.

Required scope

Chat.AttachmentsRoot requires Chat.Root.

Chat.AttachmentsRoot requires Upload.Root.

Props

4 documented props

ChatAttachments.Root props
PropTypeDefault
bucket
string—
maxSize
number—
accept
string—
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/chat-attachments/src/headless/attachments-root.tsx

ChatAttachments.Availablegate

ChatAttachments.Available conditionally renders its children.

Props

1 documented props

ChatAttachments.Available props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/chat-attachments/src/headless/attachments-available.tsx

ChatAttachments.Surfacecontent · <div>

Paste and drop share the upload guard and queue.

Props

3 documented props · Native <div> attributes supported

ChatAttachments.Surface props
PropTypeDefault
longPasteThreshold

Characters; false keeps all pasted text inline.

number | false2000
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/chat-attachments/src/headless/attachment-surface.tsx

ChatAttachments.Errorgate

ChatAttachments.Error conditionally renders its children.

Props

1 documented props

ChatAttachments.Error props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/chat-attachments/src/headless/attachment-error.tsx

ChatAttachments.Retryaction · <button>

ChatAttachments.Retry renders a button element.

Props

2 documented props · Native <button> attributes supported

ChatAttachments.Retry props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/chat-attachments/src/headless/retry-attachments.tsx

ChatDictation.Rootscope

The existing dictation engine writes into the same draft as the native chat composer.

Required scope

ChatDictation.Root requires Chat.Root.

ChatDictation requires Chat.Root.

ChatDictation requires Dictation.Root.

Props

1 documented props

ChatDictation.Root props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/chat-dictation/root.tsx

ChatDictation.Inputinput · <textarea>

Dictation.Field remains the sole owner of editing and caret restoration.

Required scope

ChatDictation.Input requires ChatDictation.Root.

Props

2 documented props · Native <textarea> attributes supported

ChatDictation.Input props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/chat-dictation/input.tsx

ChatDictation.Voicecontent · <div>

Keep AnimatePresence mounted across the recording-to-text transition.

Required scope

ChatDictation.Voice requires ChatDictation.Root.

Props

2 documented props · Native <div> attributes supported

ChatDictation.Voice props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/chat-dictation/voice.tsx

ChatDictation.Textcontent · <div>

Keep the actual field mounted so its caret owner survives the voice surface.

Required scope

ChatDictation.Text requires ChatDictation.Root.

Props

2 documented props · Native <div> attributes supported

ChatDictation.Text props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/chat-dictation/text.tsx

ChatDictation.Confirmaction · <button>

ChatDictation.Confirm renders a button element.

Required scope

ChatDictation.Confirm requires ChatDictation.Root.

Props

2 documented props · Native <button> attributes supported

ChatDictation.Confirm props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/chat-dictation/confirm.tsx

Upload.Rootscope

The queue, its limits, and its field registration when it has a name inside a Composer.

Props

12 documented props

Upload.Root props
PropTypeDefault
name

The key of this value in a Composer's message. With a name, inside a Composer, the uploader is a field: its value is the finished files, and it holds the submit while one uploads. Without one, or outside a Composer, it is a plain uploader.

string—
enabled

Left out or true: required, and a missing service throws. "optional": renders its children and every upload part does nothing, which is what a pattern's paperclip passes. false: off. A Composer whose sink takes no files turns it off too.

Enabled—
config

The file-storage config, "default" when left out.

string—
bucket
string—
path

The directory files land in.

string"/"
maxSize

Bytes. A larger file is turned away before anything is sent. The server's own limit, in services/file-storage/limits.ts, applies too: the lower of the two is the one enforced.

number—
maxFiles
number—
accept

An accept attribute: "image/*,.pdf". Offered to the picker and checked on the way in.

string—
multipart

Files from 5 MiB go up in resumable parts wherever the backend has them, so a large file survives a dropped connection and can be paused. On unless turned off: a screen that had to opt in sent a 2 GB file as one request. A backend without parts is sent whole.

booleantrue
includeHidden

Hidden files inside a folder (.DS_Store, .git/…, Thumbs.db) are left out of what a folder drop or folder pick brings in. Say includeHidden to send them. A hidden file chosen on its own is always taken.

booleanfalse
ifExists

What a name that is taken does: replace, keep both, refuse, or "ask" and wait to be told. Left out, replace.

IfExists | "ask"—
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/upload-root.tsx

When something is missing

No service configuration
Install the ai-chat setup below and import "@/services". Required service roots report missing setup; gates do not replace that configuration.
Missing capability or parent scope
Follow each part’s context requirements and the example composition. Capability-aware controls hide when the provider cannot perform their action.
Read the setup guide →