@assistant-ui/mcp-docs-server 0.1.25 → 0.1.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/.docs/organized/code-examples/waterfall.md +4 -4
  2. package/.docs/organized/code-examples/with-a2a.md +5 -5
  3. package/.docs/organized/code-examples/with-ag-ui.md +6 -6
  4. package/.docs/organized/code-examples/with-ai-sdk-v6.md +7 -7
  5. package/.docs/organized/code-examples/with-artifacts.md +7 -7
  6. package/.docs/organized/code-examples/with-assistant-transport.md +5 -5
  7. package/.docs/organized/code-examples/with-chain-of-thought.md +7 -7
  8. package/.docs/organized/code-examples/with-cloud-standalone.md +8 -8
  9. package/.docs/organized/code-examples/with-cloud.md +7 -7
  10. package/.docs/organized/code-examples/with-custom-thread-list.md +7 -7
  11. package/.docs/organized/code-examples/with-elevenlabs-conversational.md +511 -0
  12. package/.docs/organized/code-examples/with-elevenlabs-scribe.md +10 -10
  13. package/.docs/organized/code-examples/with-expo.md +18 -18
  14. package/.docs/organized/code-examples/with-external-store.md +5 -5
  15. package/.docs/organized/code-examples/with-ffmpeg.md +220 -66
  16. package/.docs/organized/code-examples/with-google-adk.md +6 -6
  17. package/.docs/organized/code-examples/with-heat-graph.md +4 -4
  18. package/.docs/organized/code-examples/with-interactables.md +836 -0
  19. package/.docs/organized/code-examples/with-langgraph.md +6 -6
  20. package/.docs/organized/code-examples/with-livekit.md +591 -0
  21. package/.docs/organized/code-examples/with-parent-id-grouping.md +6 -6
  22. package/.docs/organized/code-examples/with-react-hook-form.md +8 -8
  23. package/.docs/organized/code-examples/with-react-ink.md +3 -3
  24. package/.docs/organized/code-examples/with-react-router.md +11 -11
  25. package/.docs/organized/code-examples/with-store.md +11 -6
  26. package/.docs/organized/code-examples/with-tanstack.md +8 -8
  27. package/.docs/organized/code-examples/with-tap-runtime.md +8 -8
  28. package/.docs/raw/blog/2026-03-launch-week/index.mdx +31 -0
  29. package/.docs/raw/docs/(docs)/cli.mdx +60 -0
  30. package/.docs/raw/docs/(docs)/copilots/model-context.mdx +9 -1
  31. package/.docs/raw/docs/(docs)/guides/attachments.mdx +65 -4
  32. package/.docs/raw/docs/(docs)/guides/interactables.mdx +354 -0
  33. package/.docs/raw/docs/(docs)/guides/message-timing.mdx +3 -3
  34. package/.docs/raw/docs/(docs)/guides/multi-agent.mdx +1 -0
  35. package/.docs/raw/docs/(docs)/guides/tool-ui.mdx +29 -0
  36. package/.docs/raw/docs/(docs)/guides/voice.mdx +333 -0
  37. package/.docs/raw/docs/(reference)/api-reference/primitives/composer.mdx +128 -0
  38. package/.docs/raw/docs/(reference)/api-reference/primitives/message-part.mdx +23 -0
  39. package/.docs/raw/docs/cloud/ai-sdk-assistant-ui.mdx +6 -0
  40. package/.docs/raw/docs/cloud/ai-sdk.mdx +81 -1
  41. package/.docs/raw/docs/ink/primitives.mdx +141 -0
  42. package/.docs/raw/docs/primitives/action-bar.mdx +351 -0
  43. package/.docs/raw/docs/primitives/assistant-modal.mdx +215 -0
  44. package/.docs/raw/docs/primitives/attachment.mdx +216 -0
  45. package/.docs/raw/docs/primitives/branch-picker.mdx +221 -0
  46. package/.docs/raw/docs/primitives/chain-of-thought.mdx +311 -0
  47. package/.docs/raw/docs/primitives/composer.mdx +526 -0
  48. package/.docs/raw/docs/primitives/error.mdx +141 -0
  49. package/.docs/raw/docs/primitives/index.mdx +98 -0
  50. package/.docs/raw/docs/primitives/message.mdx +524 -0
  51. package/.docs/raw/docs/primitives/selection-toolbar.mdx +165 -0
  52. package/.docs/raw/docs/primitives/suggestion.mdx +242 -0
  53. package/.docs/raw/docs/primitives/thread-list.mdx +404 -0
  54. package/.docs/raw/docs/primitives/thread.mdx +482 -0
  55. package/.docs/raw/docs/runtimes/a2a/index.mdx +4 -0
  56. package/.docs/raw/docs/runtimes/ai-sdk/v6.mdx +2 -2
  57. package/.docs/raw/docs/runtimes/assistant-transport.mdx +6 -2
  58. package/.docs/raw/docs/ui/context-display.mdx +2 -2
  59. package/.docs/raw/docs/ui/mention.mdx +168 -0
  60. package/.docs/raw/docs/ui/model-selector.mdx +1 -1
  61. package/.docs/raw/docs/ui/voice.mdx +172 -0
  62. package/package.json +3 -4
@@ -0,0 +1,526 @@
1
+ ---
2
+ title: Composer
3
+ description: Build custom message input UIs with full control over layout and behavior.
4
+ ---
5
+
6
+ import { ComposerPrimitiveSample } from "@/components/docs/samples/composer-primitive";
7
+ import { ComposerPrimitive as ComposerPrimitiveDocs } from "@/generated/primitiveDocs";
8
+
9
+ The Composer primitive is the interface for composing new messages or editing existing ones. It handles submit behavior, keyboard shortcuts, focus management, attachment state, and streaming status. You provide the UI.
10
+
11
+ <Tabs items={["Preview", "Code"]}>
12
+ <Tab>
13
+ <ComposerPrimitiveSample />
14
+ </Tab>
15
+ <Tab>
16
+ ```tsx
17
+ import { ComposerPrimitive } from "@assistant-ui/react";
18
+ import { ArrowUpIcon } from "lucide-react";
19
+
20
+ export function MinimalComposer() {
21
+ return (
22
+ <ComposerPrimitive.Root className="flex w-full flex-col rounded-3xl border bg-muted">
23
+ <ComposerPrimitive.Input
24
+ placeholder="Ask anything..."
25
+ className="min-h-10 w-full resize-none bg-transparent px-5 pt-4 pb-3 text-sm focus:outline-none"
26
+ rows={1}
27
+ />
28
+ <div className="flex items-center justify-end px-3 pb-3">
29
+ <ComposerPrimitive.Send className="flex size-8 items-center justify-center rounded-full bg-primary text-primary-foreground disabled:opacity-30">
30
+ <ArrowUpIcon className="size-4" />
31
+ </ComposerPrimitive.Send>
32
+ </div>
33
+ </ComposerPrimitive.Root>
34
+ );
35
+ }
36
+ ```
37
+ </Tab>
38
+ </Tabs>
39
+
40
+ ## Quick Start
41
+
42
+ Minimal example:
43
+
44
+ ```tsx
45
+ import { ComposerPrimitive } from "@assistant-ui/react";
46
+
47
+ <ComposerPrimitive.Root>
48
+ <ComposerPrimitive.Input placeholder="Ask anything..." />
49
+ <ComposerPrimitive.Send>Send</ComposerPrimitive.Send>
50
+ </ComposerPrimitive.Root>
51
+ ```
52
+
53
+ `Root` renders a `<form>`, `Input` renders a `<textarea>`, and `Send` renders a `<button>`. Each part renders its native element by default, and supports `asChild` for element substitution.
54
+
55
+ <Callout type="info">
56
+ Runtime setup: primitives require runtime context. Wrap your UI in `AssistantRuntimeProvider` with a runtime (for example `useLocalRuntime(...)`). See [Pick a Runtime](/docs/runtimes/pick-a-runtime).
57
+ </Callout>
58
+
59
+ ## Core Concepts
60
+
61
+ ### New Message vs Edit Mode
62
+
63
+ A Composer placed inside a **Thread** composes new messages. A Composer placed inside a **Message** edits that message. The same primitives handle both, and the behavior changes automatically based on context.
64
+
65
+ ```tsx
66
+ // New message composer
67
+ <ThreadPrimitive.Root>
68
+ <ComposerPrimitive.Root>
69
+ <ComposerPrimitive.Input />
70
+ <ComposerPrimitive.Send>Send</ComposerPrimitive.Send>
71
+ </ComposerPrimitive.Root>
72
+ </ThreadPrimitive.Root>
73
+
74
+ // Edit composer (inside a message)
75
+ <MessagePrimitive.Root>
76
+ <ComposerPrimitive.Root>
77
+ <ComposerPrimitive.Input />
78
+ <ComposerPrimitive.Send>Save</ComposerPrimitive.Send>
79
+ <ComposerPrimitive.Cancel>Cancel</ComposerPrimitive.Cancel>
80
+ </ComposerPrimitive.Root>
81
+ </MessagePrimitive.Root>
82
+ ```
83
+
84
+ ### The `asChild` Pattern
85
+
86
+ Every primitive part accepts `asChild` to merge its behavior onto your own element. This is how you use primitives with your own design system:
87
+
88
+ ```tsx
89
+ import { ComposerPrimitive } from "@assistant-ui/react";
90
+
91
+ <ComposerPrimitive.Input asChild>
92
+ <textarea
93
+ className="my-custom-textarea"
94
+ placeholder="Type here..."
95
+ />
96
+ </ComposerPrimitive.Input>
97
+
98
+ <ComposerPrimitive.Send asChild>
99
+ <MyButton variant="primary">Send</MyButton>
100
+ </ComposerPrimitive.Send>
101
+ ```
102
+
103
+ The primitive's behavior (keyboard handling, disabled state, form submission) is merged onto your element. Your styles, your component, primitive wiring.
104
+
105
+ ### Unstable Mentions
106
+
107
+ Composer also includes an unstable mention system for `@`-triggered popovers. It is built around `ComposerPrimitive.Unstable_MentionRoot` and intended for rich inputs like `LexicalComposerInput`.
108
+
109
+ ```tsx
110
+ <ComposerPrimitive.Unstable_MentionRoot>
111
+ <ComposerPrimitive.Root>
112
+ <LexicalComposerInput placeholder="Type @ to mention a tool..." />
113
+ <ComposerPrimitive.Unstable_MentionPopover />
114
+ </ComposerPrimitive.Root>
115
+ </ComposerPrimitive.Unstable_MentionRoot>
116
+ ```
117
+
118
+ ## Parts
119
+
120
+ ### Root
121
+
122
+ Form container for message composition. Renders a `<form>` element unless `asChild` is set.
123
+
124
+ ```tsx
125
+ <ComposerPrimitive.Root className="flex w-full flex-col rounded-3xl border bg-muted">
126
+ <ComposerPrimitive.Input placeholder="Ask anything..." />
127
+ <ComposerPrimitive.Send>Send</ComposerPrimitive.Send>
128
+ </ComposerPrimitive.Root>
129
+ ```
130
+
131
+ ### Input
132
+
133
+ Text input with keyboard shortcuts. Renders a `<textarea>` element unless `asChild` is set.
134
+
135
+ ```tsx
136
+ <ComposerPrimitive.Input
137
+ submitMode="ctrlEnter"
138
+ cancelOnEscape
139
+ placeholder="Ask anything..."
140
+ />
141
+ ```
142
+
143
+ <PrimitivesTypeTable type="ComposerPrimitiveInputProps" parameters={ComposerPrimitiveDocs.Input.props.filter(p => p.name !== "asChild")} />
144
+
145
+ ### Send
146
+
147
+ Submits the composer form. Renders a `<button>` element unless `asChild` is set.
148
+
149
+ ```tsx
150
+ <ComposerPrimitive.Send className="rounded-full bg-primary px-3 py-2 text-primary-foreground">
151
+ Send
152
+ </ComposerPrimitive.Send>
153
+ ```
154
+
155
+ ### Cancel
156
+
157
+ Cancels the current composition or edit session. Renders a `<button>` element unless `asChild` is set.
158
+
159
+ ```tsx
160
+ <ComposerPrimitive.Cancel className="rounded-md px-3 py-2 text-sm hover:bg-muted">
161
+ Cancel
162
+ </ComposerPrimitive.Cancel>
163
+ ```
164
+
165
+ ### AddAttachment
166
+
167
+ Opens file picker for attachments. Renders a `<button>` element unless `asChild` is set.
168
+
169
+ ```tsx
170
+ <ComposerPrimitive.AddAttachment multiple>
171
+ Attach Files
172
+ </ComposerPrimitive.AddAttachment>
173
+ ```
174
+
175
+ <PrimitivesTypeTable type="ComposerPrimitiveAddAttachmentProps" parameters={ComposerPrimitiveDocs.AddAttachment.props.filter(p => p.name !== "asChild")} />
176
+
177
+ ### Attachments
178
+
179
+ Renders each attachment. Prefer the children render function for new code.
180
+
181
+ ```tsx
182
+ <ComposerPrimitive.Attachments>
183
+ {({ attachment }) => {
184
+ if (attachment.type === "image") return <ImagePreview />;
185
+ if (attachment.type === "document") return <DocumentPreview />;
186
+ return <GenericPreview />;
187
+ }}
188
+ </ComposerPrimitive.Attachments>
189
+ ```
190
+
191
+ <PrimitivesTypeTable type="ComposerPrimitiveAttachmentsProps" parameters={ComposerPrimitiveDocs.Attachments.props} />
192
+
193
+ ### AttachmentByIndex
194
+
195
+ Renders a single attachment at a specific index.
196
+
197
+ ```tsx
198
+ <ComposerPrimitive.AttachmentByIndex
199
+ index={0}
200
+ components={{ Attachment: MyAttachment }}
201
+ />
202
+ ```
203
+
204
+ <PrimitivesTypeTable type="ComposerPrimitiveAttachmentByIndexProps" parameters={ComposerPrimitiveDocs.AttachmentByIndex.props} />
205
+
206
+ ### AttachmentDropzone
207
+
208
+ Drag-and-drop zone for file attachments. Sets `data-dragging` when a file is being dragged over it. Renders a `<div>` element unless `asChild` is set.
209
+
210
+ ```tsx
211
+ <ComposerPrimitive.AttachmentDropzone className="rounded-xl border-2 border-dashed data-[dragging]:border-primary data-[dragging]:bg-primary/5">
212
+ <ComposerPrimitive.Root>
213
+ ...
214
+ </ComposerPrimitive.Root>
215
+ </ComposerPrimitive.AttachmentDropzone>
216
+ ```
217
+
218
+ <PrimitivesTypeTable type="ComposerPrimitiveAttachmentDropzoneProps" parameters={ComposerPrimitiveDocs.AttachmentDropzone.props.filter(p => p.name !== "asChild")} />
219
+
220
+ ### Dictate
221
+
222
+ Starts a dictation session. Renders a `<button>` element unless `asChild` is set.
223
+
224
+ ```tsx
225
+ <ComposerPrimitive.Dictate className="rounded-md px-3 py-2 text-sm hover:bg-muted">
226
+ Start Dictation
227
+ </ComposerPrimitive.Dictate>
228
+ ```
229
+
230
+ ### StopDictation
231
+
232
+ Stops the current dictation session. Renders a `<button>` element unless `asChild` is set.
233
+
234
+ ```tsx
235
+ <ComposerPrimitive.StopDictation className="rounded-md px-3 py-2 text-sm hover:bg-muted">
236
+ Stop Dictation
237
+ </ComposerPrimitive.StopDictation>
238
+ ```
239
+
240
+ ### DictationTranscript
241
+
242
+ Renders the interim transcript while dictation is active. Renders a `<span>` element unless `asChild` is set.
243
+
244
+ ```tsx
245
+ <ComposerPrimitive.DictationTranscript className="text-sm text-muted-foreground" />
246
+ ```
247
+
248
+ ### If (deprecated)
249
+
250
+ <Callout type="warn">
251
+ Deprecated. Use [`AuiIf`](/docs/api-reference/primitives/assistant-if) instead.
252
+ </Callout>
253
+
254
+ ```tsx
255
+ // Before (deprecated)
256
+ <ComposerPrimitive.If editing>...</ComposerPrimitive.If>
257
+ <ComposerPrimitive.If dictation>...</ComposerPrimitive.If>
258
+
259
+ // After
260
+ <AuiIf condition={(s) => s.composer.isEditing}>...</AuiIf>
261
+ <AuiIf condition={(s) => s.composer.dictation != null}>...</AuiIf>
262
+ ```
263
+
264
+ ### Quote
265
+
266
+ Container for quoted text preview inside the composer. Only renders when a quote is set. Renders a `<div>` element unless `asChild` is set.
267
+
268
+ ```tsx
269
+ <ComposerPrimitive.Quote className="rounded-lg border bg-background px-3 py-2 text-sm">
270
+ <ComposerPrimitive.QuoteText />
271
+ <ComposerPrimitive.QuoteDismiss className="ml-2" />
272
+ </ComposerPrimitive.Quote>
273
+ ```
274
+
275
+ ### QuoteText
276
+
277
+ Renders the quoted text content. Renders a `<span>` element unless `asChild` is set.
278
+
279
+ ```tsx
280
+ <ComposerPrimitive.QuoteText />
281
+ ```
282
+
283
+ ### QuoteDismiss
284
+
285
+ Clears the active quote from the composer. Renders a `<button>` element unless `asChild` is set.
286
+
287
+ ```tsx
288
+ <ComposerPrimitive.QuoteDismiss className="rounded-full p-1 hover:bg-muted">
289
+ Dismiss
290
+ </ComposerPrimitive.QuoteDismiss>
291
+ ```
292
+
293
+ ### Unstable_MentionRoot
294
+
295
+ Provider that manages mention state and `@` trigger detection.
296
+
297
+ ```tsx
298
+ <ComposerPrimitive.Unstable_MentionRoot trigger="@" adapter={mentionAdapter}>
299
+ <ComposerPrimitive.Root>
300
+ <LexicalComposerInput placeholder="Type @ to mention a tool..." />
301
+ <ComposerPrimitive.Unstable_MentionPopover />
302
+ </ComposerPrimitive.Root>
303
+ </ComposerPrimitive.Unstable_MentionRoot>
304
+ ```
305
+
306
+ <PrimitivesTypeTable type="ComposerPrimitiveMentionRootProps" parameters={ComposerPrimitiveDocs.Unstable_MentionRoot.props} />
307
+
308
+ ### Unstable_MentionPopover
309
+
310
+ Container for the mention picker popover. It only renders while a trigger match is active.
311
+
312
+ ```tsx
313
+ <ComposerPrimitive.Unstable_MentionPopover className="rounded-lg border bg-popover p-1 shadow-md">
314
+ <ComposerPrimitive.Unstable_MentionCategories>
315
+ {(categories) => categories.map((category) => (
316
+ <ComposerPrimitive.Unstable_MentionCategoryItem
317
+ key={category.id}
318
+ categoryId={category.id}
319
+ >
320
+ {category.label}
321
+ </ComposerPrimitive.Unstable_MentionCategoryItem>
322
+ ))}
323
+ </ComposerPrimitive.Unstable_MentionCategories>
324
+ </ComposerPrimitive.Unstable_MentionPopover>
325
+ ```
326
+
327
+ ### Unstable_MentionCategories
328
+
329
+ Render-function primitive for the top-level mention categories.
330
+
331
+ ```tsx
332
+ <ComposerPrimitive.Unstable_MentionCategories>
333
+ {(categories) => categories.map((category) => (
334
+ <ComposerPrimitive.Unstable_MentionCategoryItem
335
+ key={category.id}
336
+ categoryId={category.id}
337
+ >
338
+ {category.label}
339
+ </ComposerPrimitive.Unstable_MentionCategoryItem>
340
+ ))}
341
+ </ComposerPrimitive.Unstable_MentionCategories>
342
+ ```
343
+
344
+ <PrimitivesTypeTable type="ComposerPrimitiveMentionCategoriesProps" parameters={ComposerPrimitiveDocs.Unstable_MentionCategories.props} />
345
+
346
+ ### Unstable_MentionCategoryItem
347
+
348
+ Button that selects a mention category and drills into its items.
349
+
350
+ ```tsx
351
+ <ComposerPrimitive.Unstable_MentionCategoryItem categoryId="tools">
352
+ Tools
353
+ </ComposerPrimitive.Unstable_MentionCategoryItem>
354
+ ```
355
+
356
+ ### Unstable_MentionItems
357
+
358
+ Render-function primitive for the items inside the currently selected category.
359
+
360
+ ```tsx
361
+ <ComposerPrimitive.Unstable_MentionItems>
362
+ {(items) => items.map((item) => (
363
+ <ComposerPrimitive.Unstable_MentionItem key={item.id} item={item} />
364
+ ))}
365
+ </ComposerPrimitive.Unstable_MentionItems>
366
+ ```
367
+
368
+ <PrimitivesTypeTable type="ComposerPrimitiveMentionItemsProps" parameters={ComposerPrimitiveDocs.Unstable_MentionItems.props} />
369
+
370
+ ### Unstable_MentionItem
371
+
372
+ Selectable mention item inside the popover.
373
+
374
+ ```tsx
375
+ <ComposerPrimitive.Unstable_MentionItem item={item}>
376
+ {item.label}
377
+ </ComposerPrimitive.Unstable_MentionItem>
378
+ ```
379
+
380
+ <PrimitivesTypeTable type="ComposerPrimitiveMentionItemProps" parameters={ComposerPrimitiveDocs.Unstable_MentionItem.props} />
381
+
382
+ ### Unstable_MentionBack
383
+
384
+ Back button used when drilling from categories into a specific item list.
385
+
386
+ ```tsx
387
+ <ComposerPrimitive.Unstable_MentionBack className="rounded-md px-2 py-1 text-sm hover:bg-accent">
388
+ Back
389
+ </ComposerPrimitive.Unstable_MentionBack>
390
+ ```
391
+
392
+ ## Patterns
393
+
394
+ ### With Attachments
395
+
396
+ ```tsx
397
+ <ComposerPrimitive.Root>
398
+ <ComposerPrimitive.Attachments>
399
+ {({ attachment }) => {
400
+ if (attachment.type === "image") return <ImagePreview />;
401
+ if (attachment.type === "document") return <DocumentPreview />;
402
+ return <GenericPreview />;
403
+ }}
404
+ </ComposerPrimitive.Attachments>
405
+ <ComposerPrimitive.Input placeholder="Ask anything..." />
406
+ <ComposerPrimitive.AddAttachment>
407
+ Attach
408
+ </ComposerPrimitive.AddAttachment>
409
+ <ComposerPrimitive.Send>Send</ComposerPrimitive.Send>
410
+ </ComposerPrimitive.Root>
411
+ ```
412
+
413
+ ### With Drag-and-Drop
414
+
415
+ Wrap your composer with `AttachmentDropzone` to support dragging files directly onto the input area:
416
+
417
+ ```tsx
418
+ <ComposerPrimitive.AttachmentDropzone className="rounded-xl border-2 border-dashed data-[dragging]:border-primary data-[dragging]:bg-primary/5">
419
+ <ComposerPrimitive.Root>
420
+ <ComposerPrimitive.Attachments>
421
+ {() => <MyAttachment />}
422
+ </ComposerPrimitive.Attachments>
423
+ <ComposerPrimitive.Input placeholder="Drop files or type..." />
424
+ <ComposerPrimitive.AddAttachment>Attach</ComposerPrimitive.AddAttachment>
425
+ <ComposerPrimitive.Send>Send</ComposerPrimitive.Send>
426
+ </ComposerPrimitive.Root>
427
+ </ComposerPrimitive.AttachmentDropzone>
428
+ ```
429
+
430
+ The dropzone sets `data-dragging` when a file is being dragged over it, so you can style the active state with CSS.
431
+
432
+ ### With Voice Input
433
+
434
+ ```tsx
435
+ <ComposerPrimitive.Root>
436
+ <ComposerPrimitive.Input placeholder="Ask or speak..." />
437
+ <AuiIf condition={(s) => s.composer.dictation != null}>
438
+ <ComposerPrimitive.DictationTranscript className="text-sm text-muted-foreground" />
439
+ </AuiIf>
440
+ <AuiIf condition={(s) => s.composer.dictation == null}>
441
+ <ComposerPrimitive.Dictate>Mic</ComposerPrimitive.Dictate>
442
+ </AuiIf>
443
+ <AuiIf condition={(s) => s.composer.dictation != null}>
444
+ <ComposerPrimitive.StopDictation>Stop</ComposerPrimitive.StopDictation>
445
+ </AuiIf>
446
+ <ComposerPrimitive.Send>Send</ComposerPrimitive.Send>
447
+ </ComposerPrimitive.Root>
448
+ ```
449
+
450
+ `DictationTranscript` renders a `<span>` showing the interim speech-to-text transcript while the user is speaking.
451
+
452
+ <Callout type="info">
453
+ Voice input requires a `DictationAdapter` configured in your runtime. See [Speech & Dictation](/docs/guides/speech) for setup.
454
+ </Callout>
455
+
456
+ ### Custom Submit Behavior
457
+
458
+ Use `onSubmit` on `Root` to intercept submission:
459
+
460
+ ```tsx
461
+ <ComposerPrimitive.Root
462
+ onSubmit={(e) => {
463
+ // Runs before the message is sent
464
+ // e.g., track analytics, transform input
465
+ // Call e.preventDefault() to cancel the send
466
+ }}
467
+ >
468
+ <ComposerPrimitive.Input />
469
+ <ComposerPrimitive.Send>Send</ComposerPrimitive.Send>
470
+ </ComposerPrimitive.Root>
471
+ ```
472
+
473
+ ### Ctrl+Enter to Submit
474
+
475
+ ```tsx
476
+ <ComposerPrimitive.Root>
477
+ <ComposerPrimitive.Input submitMode="ctrlEnter" />
478
+ <ComposerPrimitive.Send>Send</ComposerPrimitive.Send>
479
+ </ComposerPrimitive.Root>
480
+ ```
481
+
482
+ With `submitMode="ctrlEnter"`, plain Enter inserts a newline and Ctrl/Cmd+Enter submits.
483
+
484
+ ### Floating Composer
485
+
486
+ Primitives aren't bound to any layout. Here's how the floating composer on this docs site is built, using the same `ComposerPrimitive.Root` and `ComposerPrimitive.Input` positioned with CSS:
487
+
488
+ ```tsx
489
+ import { ComposerPrimitive } from "@assistant-ui/react";
490
+
491
+ function FloatingComposer() {
492
+ return (
493
+ <div className="fixed bottom-6 left-1/2 z-40 w-full max-w-md -translate-x-1/2">
494
+ <ComposerPrimitive.Root>
495
+ <div className="rounded-xl border bg-background/80 shadow-lg backdrop-blur-sm">
496
+ <ComposerPrimitive.Input
497
+ asChild
498
+ unstable_focusOnRunStart={false}
499
+ unstable_focusOnScrollToBottom={false}
500
+ >
501
+ <textarea
502
+ placeholder="Ask a question..."
503
+ className="w-full resize-none bg-transparent px-3 py-2.5 text-sm focus:outline-none"
504
+ rows={1}
505
+ />
506
+ </ComposerPrimitive.Input>
507
+ </div>
508
+ </ComposerPrimitive.Root>
509
+ </div>
510
+ );
511
+ }
512
+ ```
513
+
514
+ The primitive handles everything about composing a message. The layout, animation, and visibility logic is all yours.
515
+
516
+ ## Relationship to Components
517
+
518
+ The [Thread](/docs/ui/thread) component includes a full composer built from these primitives. If you need a working chat UI fast, start there. When you need a composer that doesn't fit inside a thread, such as a floating input, a sidebar composer, or a multi-step form, reach for `ComposerPrimitive` directly.
519
+
520
+ ## API Reference
521
+
522
+ For full prop details on every part, see the [ComposerPrimitive API Reference](/docs/api-reference/primitives/composer).
523
+
524
+ Related:
525
+ - [ThreadPrimitive](/docs/primitives/thread)
526
+ - [AttachmentPrimitive](/docs/primitives/attachment)
@@ -0,0 +1,141 @@
1
+ ---
2
+ title: Error
3
+ description: Accessible error display for messages with automatic error text extraction.
4
+ ---
5
+
6
+ import { ErrorPrimitiveSample } from "@/components/docs/samples/error-primitive";
7
+
8
+ The Error primitive renders error states on messages using an accessible `role="alert"` container with automatic error text extraction. `Root` always renders its container; `Message` only renders when the message has an error. Wrap in `MessagePrimitive.Error` if you need the entire block to be conditional.
9
+
10
+ <Tabs items={["Preview", "Code"]}>
11
+ <Tab>
12
+ <ErrorPrimitiveSample />
13
+ </Tab>
14
+ <Tab>
15
+ ```tsx
16
+ import { ErrorPrimitive, MessagePrimitive } from "@assistant-ui/react";
17
+
18
+ function AssistantMessage() {
19
+ return (
20
+ <MessagePrimitive.Root>
21
+ <MessagePrimitive.Parts />
22
+ <ErrorPrimitive.Root className="rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive">
23
+ <ErrorPrimitive.Message />
24
+ </ErrorPrimitive.Root>
25
+ </MessagePrimitive.Root>
26
+ );
27
+ }
28
+ ```
29
+ </Tab>
30
+ </Tabs>
31
+
32
+ ## Quick Start
33
+
34
+ A minimal error display below a message:
35
+
36
+ ```tsx
37
+ import { ErrorPrimitive, MessagePrimitive } from "@assistant-ui/react";
38
+
39
+ <MessagePrimitive.Root>
40
+ <MessagePrimitive.Parts />
41
+ <ErrorPrimitive.Root>
42
+ <ErrorPrimitive.Message />
43
+ </ErrorPrimitive.Root>
44
+ </MessagePrimitive.Root>
45
+ ```
46
+
47
+ `Root` renders a `<div>` with `role="alert"` for screen reader accessibility. `Message` renders a `<span>` that auto-reads the error text from message state, and it returns `null` when there is no error. `Root` itself always renders. Wrap in `<MessagePrimitive.Error>` if you want the entire block (including `Root`) to be conditional.
48
+
49
+ <Callout type="info">
50
+ ErrorPrimitive must be placed inside a `MessagePrimitive.Root` because it reads the error state from the nearest message context.
51
+ </Callout>
52
+
53
+ <Callout type="info">
54
+ Runtime setup: primitives require runtime context. Wrap your UI in `AssistantRuntimeProvider` with a runtime (for example `useLocalRuntime(...)`). See [Pick a Runtime](/docs/runtimes/pick-a-runtime).
55
+ </Callout>
56
+
57
+ ## Core Concepts
58
+
59
+ ### Auto-Rendering on Error
60
+
61
+ `Message` checks the message status and only renders when `status.type === "incomplete"` and `status.reason === "error"`. `Root` always renders its `<div role="alert">` container. For fully conditional rendering, wrap in `<MessagePrimitive.Error>`.
62
+
63
+ ### Automatic Error Text
64
+
65
+ `ErrorPrimitive.Message` reads the error object from message state and converts it to a string. If you pass `children`, they override the automatic text:
66
+
67
+ ```tsx
68
+ // Auto-reads error text from state
69
+ <ErrorPrimitive.Message />
70
+
71
+ // Custom children override the default
72
+ <ErrorPrimitive.Message>
73
+ Something went wrong. Please try again.
74
+ </ErrorPrimitive.Message>
75
+ ```
76
+
77
+ ### ErrorPrimitive vs MessagePrimitive.Error
78
+
79
+ `MessagePrimitive.Error` is a simpler alternative. It renders its children when the message has an error but does not provide `role="alert"` or auto-extract the error text. Use `ErrorPrimitive` when you want accessible error rendering with automatic text.
80
+
81
+ ```tsx
82
+ // ErrorPrimitive: accessible, auto-reads error text
83
+ <ErrorPrimitive.Root role="alert">
84
+ <ErrorPrimitive.Message />
85
+ </ErrorPrimitive.Root>
86
+
87
+ // MessagePrimitive.Error: simpler, manual text
88
+ <MessagePrimitive.Error>
89
+ <div>Something went wrong.</div>
90
+ </MessagePrimitive.Error>
91
+ ```
92
+
93
+ ## Parts
94
+
95
+ ### Root
96
+
97
+ Container for an error message block. Renders a `<div>` element unless `asChild` is set.
98
+
99
+ ```tsx
100
+ <ErrorPrimitive.Root className="rounded-md border border-destructive/20 bg-destructive/5 p-3">
101
+ <ErrorPrimitive.Message />
102
+ </ErrorPrimitive.Root>
103
+ ```
104
+
105
+ ### Message
106
+
107
+ Renders the current error text for the active message.
108
+
109
+ ```tsx
110
+ <ErrorPrimitive.Message className="text-destructive text-sm" />
111
+ ```
112
+
113
+ ## Patterns
114
+
115
+ ### Styled Error Alert
116
+
117
+ ```tsx
118
+ <ErrorPrimitive.Root className="mt-2 flex items-center gap-2 rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive">
119
+ <ErrorPrimitive.Message />
120
+ </ErrorPrimitive.Root>
121
+ ```
122
+
123
+ ### Custom Error Content
124
+
125
+ ```tsx
126
+ <ErrorPrimitive.Root className="mt-2 rounded-md border border-destructive/20 bg-destructive/5 p-3">
127
+ <p className="font-medium text-destructive text-sm">Error</p>
128
+ <ErrorPrimitive.Message className="text-destructive/80 text-sm" />
129
+ </ErrorPrimitive.Root>
130
+ ```
131
+
132
+ ## Relationship to Components
133
+
134
+ The shadcn [Thread](/docs/ui/thread) component uses `ErrorPrimitive` inside its `AssistantMessage` to display errors below the message content. If you need a pre-built error display, start there.
135
+
136
+ ## API Reference
137
+
138
+ For full prop details on every part, see the [ErrorPrimitive API Reference](/docs/api-reference/primitives/error).
139
+
140
+ Related:
141
+ - [MessagePrimitive API Reference](/docs/api-reference/primitives/message)