@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.
- package/.docs/organized/code-examples/waterfall.md +4 -4
- package/.docs/organized/code-examples/with-a2a.md +5 -5
- package/.docs/organized/code-examples/with-ag-ui.md +6 -6
- package/.docs/organized/code-examples/with-ai-sdk-v6.md +7 -7
- package/.docs/organized/code-examples/with-artifacts.md +7 -7
- package/.docs/organized/code-examples/with-assistant-transport.md +5 -5
- package/.docs/organized/code-examples/with-chain-of-thought.md +7 -7
- package/.docs/organized/code-examples/with-cloud-standalone.md +8 -8
- package/.docs/organized/code-examples/with-cloud.md +7 -7
- package/.docs/organized/code-examples/with-custom-thread-list.md +7 -7
- package/.docs/organized/code-examples/with-elevenlabs-conversational.md +511 -0
- package/.docs/organized/code-examples/with-elevenlabs-scribe.md +10 -10
- package/.docs/organized/code-examples/with-expo.md +18 -18
- package/.docs/organized/code-examples/with-external-store.md +5 -5
- package/.docs/organized/code-examples/with-ffmpeg.md +220 -66
- package/.docs/organized/code-examples/with-google-adk.md +6 -6
- package/.docs/organized/code-examples/with-heat-graph.md +4 -4
- package/.docs/organized/code-examples/with-interactables.md +836 -0
- package/.docs/organized/code-examples/with-langgraph.md +6 -6
- package/.docs/organized/code-examples/with-livekit.md +591 -0
- package/.docs/organized/code-examples/with-parent-id-grouping.md +6 -6
- package/.docs/organized/code-examples/with-react-hook-form.md +8 -8
- package/.docs/organized/code-examples/with-react-ink.md +3 -3
- package/.docs/organized/code-examples/with-react-router.md +11 -11
- package/.docs/organized/code-examples/with-store.md +11 -6
- package/.docs/organized/code-examples/with-tanstack.md +8 -8
- package/.docs/organized/code-examples/with-tap-runtime.md +8 -8
- package/.docs/raw/blog/2026-03-launch-week/index.mdx +31 -0
- package/.docs/raw/docs/(docs)/cli.mdx +60 -0
- package/.docs/raw/docs/(docs)/copilots/model-context.mdx +9 -1
- package/.docs/raw/docs/(docs)/guides/attachments.mdx +65 -4
- package/.docs/raw/docs/(docs)/guides/interactables.mdx +354 -0
- package/.docs/raw/docs/(docs)/guides/message-timing.mdx +3 -3
- package/.docs/raw/docs/(docs)/guides/multi-agent.mdx +1 -0
- package/.docs/raw/docs/(docs)/guides/tool-ui.mdx +29 -0
- package/.docs/raw/docs/(docs)/guides/voice.mdx +333 -0
- package/.docs/raw/docs/(reference)/api-reference/primitives/composer.mdx +128 -0
- package/.docs/raw/docs/(reference)/api-reference/primitives/message-part.mdx +23 -0
- package/.docs/raw/docs/cloud/ai-sdk-assistant-ui.mdx +6 -0
- package/.docs/raw/docs/cloud/ai-sdk.mdx +81 -1
- package/.docs/raw/docs/ink/primitives.mdx +141 -0
- package/.docs/raw/docs/primitives/action-bar.mdx +351 -0
- package/.docs/raw/docs/primitives/assistant-modal.mdx +215 -0
- package/.docs/raw/docs/primitives/attachment.mdx +216 -0
- package/.docs/raw/docs/primitives/branch-picker.mdx +221 -0
- package/.docs/raw/docs/primitives/chain-of-thought.mdx +311 -0
- package/.docs/raw/docs/primitives/composer.mdx +526 -0
- package/.docs/raw/docs/primitives/error.mdx +141 -0
- package/.docs/raw/docs/primitives/index.mdx +98 -0
- package/.docs/raw/docs/primitives/message.mdx +524 -0
- package/.docs/raw/docs/primitives/selection-toolbar.mdx +165 -0
- package/.docs/raw/docs/primitives/suggestion.mdx +242 -0
- package/.docs/raw/docs/primitives/thread-list.mdx +404 -0
- package/.docs/raw/docs/primitives/thread.mdx +482 -0
- package/.docs/raw/docs/runtimes/a2a/index.mdx +4 -0
- package/.docs/raw/docs/runtimes/ai-sdk/v6.mdx +2 -2
- package/.docs/raw/docs/runtimes/assistant-transport.mdx +6 -2
- package/.docs/raw/docs/ui/context-display.mdx +2 -2
- package/.docs/raw/docs/ui/mention.mdx +168 -0
- package/.docs/raw/docs/ui/model-selector.mdx +1 -1
- package/.docs/raw/docs/ui/voice.mdx +172 -0
- 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)
|