@assistant-ui/mcp-docs-server 0.1.30 → 0.1.31
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 +1 -1
- package/.docs/organized/code-examples/with-a2a.md +2 -2
- package/.docs/organized/code-examples/with-ag-ui.md +3 -3
- package/.docs/organized/code-examples/with-ai-sdk-v6.md +5 -5
- package/.docs/organized/code-examples/with-artifacts.md +5 -5
- package/.docs/organized/code-examples/with-assistant-transport.md +3 -3
- package/.docs/organized/code-examples/with-chain-of-thought.md +79 -50
- package/.docs/organized/code-examples/with-cloud-standalone.md +4 -4
- package/.docs/organized/code-examples/with-cloud.md +4 -4
- package/.docs/organized/code-examples/with-custom-thread-list.md +56 -11
- package/.docs/organized/code-examples/with-elevenlabs-conversational.md +7 -7
- package/.docs/organized/code-examples/with-elevenlabs-scribe.md +7 -7
- package/.docs/organized/code-examples/with-expo.md +16 -16
- package/.docs/organized/code-examples/with-external-store.md +2 -2
- package/.docs/organized/code-examples/with-ffmpeg.md +5 -5
- package/.docs/organized/code-examples/with-generative-ui.md +5 -5
- package/.docs/organized/code-examples/with-google-adk.md +4 -4
- package/.docs/organized/code-examples/with-heat-graph.md +1 -1
- package/.docs/organized/code-examples/with-interactables.md +5 -5
- package/.docs/organized/code-examples/with-langchain.md +3 -3
- package/.docs/organized/code-examples/with-langgraph.md +3 -3
- package/.docs/organized/code-examples/with-livekit.md +8 -8
- package/.docs/organized/code-examples/with-opencode.md +99 -54
- package/.docs/organized/code-examples/with-parent-id-grouping.md +4 -4
- package/.docs/organized/code-examples/with-react-hook-form.md +5 -5
- package/.docs/organized/code-examples/with-react-ink.md +1 -1
- package/.docs/organized/code-examples/with-react-router.md +8 -8
- package/.docs/organized/code-examples/with-store.md +1 -1
- package/.docs/organized/code-examples/with-tanstack.md +5 -5
- package/.docs/organized/code-examples/with-tap-runtime.md +2 -2
- package/.docs/raw/docs/(docs)/cli.mdx +2 -1
- package/.docs/raw/docs/(docs)/copilots/assistant-frame.mdx +1 -0
- package/.docs/raw/docs/(docs)/copilots/make-assistant-tool-ui.mdx +10 -3
- package/.docs/raw/docs/(docs)/copilots/make-assistant-tool.mdx +8 -3
- package/.docs/raw/docs/(docs)/copilots/make-assistant-visible.mdx +1 -0
- package/.docs/raw/docs/(docs)/copilots/model-context.mdx +1 -0
- package/.docs/raw/docs/(docs)/copilots/motivation.mdx +1 -0
- package/.docs/raw/docs/(docs)/copilots/use-assistant-instructions.mdx +1 -0
- package/.docs/raw/docs/(docs)/devtools.mdx +1 -0
- package/.docs/raw/docs/(docs)/index.mdx +1 -0
- package/.docs/raw/docs/(docs)/installation.mdx +1 -0
- package/.docs/raw/docs/(docs)/rtl.mdx +1 -0
- package/.docs/raw/docs/(reference)/api-reference/adapters/attachments.mdx +34 -0
- package/.docs/raw/docs/(reference)/api-reference/adapters/feedback-speech.mdx +41 -0
- package/.docs/raw/docs/(reference)/api-reference/adapters/index.mdx +26 -0
- package/.docs/raw/docs/(reference)/api-reference/adapters/persistence.mdx +34 -0
- package/.docs/raw/docs/(reference)/api-reference/adapters/runtime.mdx +31 -0
- package/.docs/raw/docs/(reference)/api-reference/context-providers/index.mdx +20 -0
- package/.docs/raw/docs/(reference)/api-reference/hooks/index.mdx +26 -0
- package/.docs/raw/docs/(reference)/api-reference/hooks/model-context.mdx +72 -0
- package/.docs/raw/docs/(reference)/api-reference/hooks/runtimes.mdx +41 -0
- package/.docs/raw/docs/(reference)/api-reference/hooks/state.mdx +48 -0
- package/.docs/raw/docs/(reference)/api-reference/hooks/utilities.mdx +30 -0
- package/.docs/raw/docs/(reference)/api-reference/integrations/index.mdx +23 -0
- package/.docs/raw/docs/(reference)/api-reference/overview.mdx +21 -0
- package/.docs/raw/docs/(reference)/api-reference/primitives/assistant-if.mdx +7 -0
- package/.docs/raw/docs/(reference)/api-reference/primitives/index.mdx +65 -0
- package/.docs/raw/docs/(reference)/api-reference/primitives/message.mdx +50 -6
- package/.docs/raw/docs/(reference)/api-reference/primitives/thread-list.mdx +15 -0
- package/.docs/raw/docs/(reference)/api-reference/primitives/thread.mdx +36 -1
- package/.docs/raw/docs/(reference)/api-reference/runtimes/index.mdx +38 -0
- package/.docs/raw/docs/(reference)/api-reference/runtimes/thread-list-runtime.mdx +5 -0
- package/.docs/raw/docs/(reference)/migrations/v0-14.mdx +144 -6
- package/.docs/raw/docs/cloud/ai-sdk-assistant-ui.mdx +230 -2
- package/.docs/raw/docs/cloud/ai-sdk.mdx +221 -3
- package/.docs/raw/docs/cloud/langgraph.mdx +274 -2
- package/.docs/raw/docs/{(docs)/guides → guides}/attachments.mdx +41 -36
- package/.docs/raw/docs/guides/branching.mdx +76 -0
- package/.docs/raw/docs/guides/chain-of-thought.mdx +166 -0
- package/.docs/raw/docs/{(docs)/guides → guides}/context-api.mdx +50 -22
- package/.docs/raw/docs/{(docs)/guides → guides}/dictation.mdx +2 -0
- package/.docs/raw/docs/guides/editing.mdx +102 -0
- package/.docs/raw/docs/guides/index.mdx +103 -0
- package/.docs/raw/docs/{(docs)/guides → guides}/interactables.mdx +49 -0
- package/.docs/raw/docs/{(docs)/guides → guides}/latex.mdx +51 -8
- package/.docs/raw/docs/{(docs)/guides → guides}/mentions.mdx +61 -86
- package/.docs/raw/docs/{(docs)/guides → guides}/message-timing.mdx +8 -2
- package/.docs/raw/docs/{(docs)/guides → guides}/multi-agent.mdx +64 -4
- package/.docs/raw/docs/{(docs)/guides → guides}/quoting.mdx +10 -17
- package/.docs/raw/docs/{(docs)/guides → guides}/slash-commands.mdx +103 -37
- package/.docs/raw/docs/guides/speech.mdx +156 -0
- package/.docs/raw/docs/{(docs)/guides → guides}/suggestions.mdx +21 -83
- package/.docs/raw/docs/{(docs)/guides → guides}/tool-ui.mdx +108 -36
- package/.docs/raw/docs/{(docs)/guides → guides}/tools.mdx +131 -35
- package/.docs/raw/docs/{(docs)/guides → guides}/voice.mdx +39 -0
- package/.docs/raw/docs/ink/index.mdx +1 -3
- package/.docs/raw/docs/ink/migration.mdx +1 -3
- package/.docs/raw/docs/ink/primitives.mdx +37 -1
- package/.docs/raw/docs/integrations/attachments/custom-adapter.mdx +520 -0
- package/.docs/raw/docs/integrations/auth/better-auth.mdx +191 -0
- package/.docs/raw/docs/integrations/auth/clerk.mdx +172 -0
- package/.docs/raw/docs/integrations/auth/next-auth.mdx +196 -0
- package/.docs/raw/docs/integrations/frameworks/ai-sdk.mdx +79 -0
- package/.docs/raw/docs/integrations/frameworks/mastra/full-stack.mdx +188 -0
- package/.docs/raw/docs/integrations/frameworks/mastra/overview.mdx +57 -0
- package/.docs/raw/docs/integrations/frameworks/mastra/separate-server.mdx +201 -0
- package/.docs/raw/docs/integrations/gateways/index.mdx +157 -0
- package/.docs/raw/docs/integrations/index.mdx +173 -0
- package/.docs/raw/docs/integrations/observability/helicone.mdx +130 -0
- package/.docs/raw/docs/integrations/observability/langfuse.mdx +156 -0
- package/.docs/raw/docs/integrations/observability/langsmith.mdx +146 -0
- package/.docs/raw/docs/integrations/persistence/custom-adapter.mdx +712 -0
- package/.docs/raw/docs/integrations/tools/mcp.mdx +267 -0
- package/.docs/raw/docs/primitives/action-bar.mdx +1 -0
- package/.docs/raw/docs/primitives/assistant-modal.mdx +1 -0
- package/.docs/raw/docs/primitives/attachment.mdx +1 -0
- package/.docs/raw/docs/primitives/branch-picker.mdx +1 -0
- package/.docs/raw/docs/primitives/chain-of-thought.mdx +90 -85
- package/.docs/raw/docs/primitives/composer.mdx +2 -1
- package/.docs/raw/docs/primitives/error.mdx +1 -0
- package/.docs/raw/docs/primitives/index.mdx +2 -1
- package/.docs/raw/docs/primitives/message.mdx +68 -5
- package/.docs/raw/docs/primitives/selection-toolbar.mdx +1 -0
- package/.docs/raw/docs/primitives/suggestion.mdx +1 -0
- package/.docs/raw/docs/primitives/thread-list.mdx +39 -0
- package/.docs/raw/docs/primitives/thread.mdx +16 -13
- package/.docs/raw/docs/react-native/index.mdx +1 -3
- package/.docs/raw/docs/react-native/migration.mdx +1 -3
- package/.docs/raw/docs/runtimes/a2a/client-and-hooks.mdx +396 -0
- package/.docs/raw/docs/runtimes/a2a/overview.mdx +60 -0
- package/.docs/raw/docs/runtimes/a2a/quickstart.mdx +216 -0
- package/.docs/raw/docs/runtimes/ag-ui/overview.mdx +70 -0
- package/.docs/raw/docs/runtimes/ag-ui/quickstart.mdx +243 -0
- package/.docs/raw/docs/runtimes/ag-ui/runtime-options.mdx +123 -0
- package/.docs/raw/docs/runtimes/ai-sdk/overview.mdx +52 -0
- package/.docs/raw/docs/runtimes/ai-sdk/v4-legacy.mdx +71 -131
- package/.docs/raw/docs/runtimes/ai-sdk/v5-legacy.mdx +69 -63
- package/.docs/raw/docs/runtimes/ai-sdk/v6.mdx +330 -123
- package/.docs/raw/docs/runtimes/concepts/adapters.mdx +265 -0
- package/.docs/raw/docs/runtimes/concepts/architecture.mdx +125 -0
- package/.docs/raw/docs/runtimes/concepts/stability.mdx +67 -0
- package/.docs/raw/docs/runtimes/concepts/threads.mdx +428 -0
- package/.docs/raw/docs/runtimes/custom/assistant-transport.mdx +703 -0
- package/.docs/raw/docs/runtimes/custom/data-stream.mdx +323 -0
- package/.docs/raw/docs/runtimes/custom/external-store.mdx +253 -1236
- package/.docs/raw/docs/runtimes/custom/local-runtime.mdx +746 -0
- package/.docs/raw/docs/runtimes/custom/overview.mdx +71 -0
- package/.docs/raw/docs/runtimes/google-adk/api.mdx +256 -0
- package/.docs/raw/docs/runtimes/google-adk/hooks.mdx +717 -0
- package/.docs/raw/docs/runtimes/google-adk/overview.mdx +69 -0
- package/.docs/raw/docs/runtimes/google-adk/quickstart.mdx +229 -0
- package/.docs/raw/docs/runtimes/langchain.mdx +533 -0
- package/.docs/raw/docs/runtimes/langgraph/generative-ui.mdx +305 -0
- package/.docs/raw/docs/runtimes/langgraph/interrupts.mdx +104 -0
- package/.docs/raw/docs/runtimes/langgraph/overview.mdx +84 -0
- package/.docs/raw/docs/runtimes/langgraph/quickstart.mdx +496 -0
- package/.docs/raw/docs/runtimes/langgraph/streaming.mdx +127 -0
- package/.docs/raw/docs/runtimes/langgraph/threads.mdx +113 -0
- package/.docs/raw/docs/runtimes/langgraph/tutorial/introduction.mdx +3 -3
- package/.docs/raw/docs/runtimes/langgraph/tutorial/part-1.mdx +0 -23
- package/.docs/raw/docs/runtimes/langgraph/tutorial/part-2.mdx +1 -1
- package/.docs/raw/docs/runtimes/opencode/hooks.mdx +191 -0
- package/.docs/raw/docs/runtimes/opencode/overview.mdx +48 -0
- package/.docs/raw/docs/runtimes/opencode/quickstart.mdx +119 -0
- package/.docs/raw/docs/runtimes/pick-a-runtime.mdx +71 -203
- package/.docs/raw/docs/ui/accordion.mdx +1 -0
- package/.docs/raw/docs/ui/assistant-modal.mdx +1 -0
- package/.docs/raw/docs/ui/assistant-sidebar.mdx +1 -0
- package/.docs/raw/docs/ui/attachment.mdx +1 -0
- package/.docs/raw/docs/ui/badge.mdx +1 -0
- package/.docs/raw/docs/ui/composer-trigger-popover.mdx +1 -0
- package/.docs/raw/docs/ui/context-display.mdx +1 -0
- package/.docs/raw/docs/ui/diff-viewer.mdx +1 -0
- package/.docs/raw/docs/ui/directive-text.mdx +1 -0
- package/.docs/raw/docs/ui/file.mdx +1 -0
- package/.docs/raw/docs/ui/image.mdx +1 -0
- package/.docs/raw/docs/ui/markdown.mdx +2 -14
- package/.docs/raw/docs/ui/mermaid.mdx +1 -0
- package/.docs/raw/docs/ui/message-timing.mdx +3 -2
- package/.docs/raw/docs/ui/model-selector.mdx +1 -0
- package/.docs/raw/docs/ui/part-grouping.mdx +325 -313
- package/.docs/raw/docs/ui/quote.mdx +1 -0
- package/.docs/raw/docs/ui/reasoning.mdx +66 -33
- package/.docs/raw/docs/ui/scrollbar.mdx +1 -0
- package/.docs/raw/docs/ui/select.mdx +1 -0
- package/.docs/raw/docs/ui/sources.mdx +1 -0
- package/.docs/raw/docs/ui/streamdown.mdx +1 -0
- package/.docs/raw/docs/ui/syntax-highlighting.mdx +1 -0
- package/.docs/raw/docs/ui/tabs.mdx +1 -0
- package/.docs/raw/docs/ui/thread-list.mdx +17 -0
- package/.docs/raw/docs/ui/thread.mdx +56 -1
- package/.docs/raw/docs/ui/tool-fallback.mdx +1 -0
- package/.docs/raw/docs/ui/tool-group.mdx +39 -11
- package/.docs/raw/docs/ui/voice.mdx +1 -0
- package/.docs/raw/docs/utilities/heat-graph.mdx +1 -0
- package/.docs/raw/docs/utilities/react-o11y.mdx +278 -0
- package/.docs/raw/docs/utilities/tw-shimmer.mdx +1 -0
- package/package.json +3 -3
- package/src/tools/tests/path-traversal.test.ts +1 -1
- package/.docs/raw/docs/(docs)/guides/branching.mdx +0 -65
- package/.docs/raw/docs/(docs)/guides/chain-of-thought.mdx +0 -164
- package/.docs/raw/docs/(docs)/guides/editing.mdx +0 -66
- package/.docs/raw/docs/(docs)/guides/speech.mdx +0 -38
- package/.docs/raw/docs/runtimes/a2a/index.mdx +0 -298
- package/.docs/raw/docs/runtimes/assistant-transport.mdx +0 -1033
- package/.docs/raw/docs/runtimes/custom/custom-thread-list.mdx +0 -314
- package/.docs/raw/docs/runtimes/custom/local.mdx +0 -1464
- package/.docs/raw/docs/runtimes/data-stream.mdx +0 -422
- package/.docs/raw/docs/runtimes/google-adk/index.mdx +0 -686
- package/.docs/raw/docs/runtimes/helicone.mdx +0 -61
- package/.docs/raw/docs/runtimes/langchain/comparison.mdx +0 -60
- package/.docs/raw/docs/runtimes/langchain/index.mdx +0 -210
- package/.docs/raw/docs/runtimes/langgraph/index.mdx +0 -699
- package/.docs/raw/docs/runtimes/langgraph/tutorial/index.mdx +0 -12
- package/.docs/raw/docs/runtimes/langserve.mdx +0 -116
- package/.docs/raw/docs/runtimes/mastra/full-stack-integration.mdx +0 -218
- package/.docs/raw/docs/runtimes/mastra/overview.mdx +0 -18
- package/.docs/raw/docs/runtimes/mastra/separate-server-integration.mdx +0 -217
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Mentions
|
|
3
3
|
description: Let users @-mention tools or custom items in the composer to guide the LLM.
|
|
4
|
+
platforms: ["react"]
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
Mentions let users type `@` in the composer to open a popover picker, select an item (e.g. a tool), and insert a directive into the message text. The LLM can then use the directive as a hint.
|
|
@@ -82,6 +83,63 @@ const myAdapter: Unstable_TriggerAdapter = {
|
|
|
82
83
|
};
|
|
83
84
|
```
|
|
84
85
|
|
|
86
|
+
### Async Mention Search
|
|
87
|
+
|
|
88
|
+
The adapter interface is synchronous, but the data it reads can come from any async source. Load results into React state (or a query cache) and read the current snapshot inside the adapter methods. The adapter re-creates on each render, so the popover always sees the latest results.
|
|
89
|
+
|
|
90
|
+
**With React state and `useEffect`:**
|
|
91
|
+
|
|
92
|
+
```tsx
|
|
93
|
+
import { useState, useEffect, useMemo } from "react";
|
|
94
|
+
import type { Unstable_TriggerAdapter } from "@assistant-ui/core";
|
|
95
|
+
|
|
96
|
+
function useUserMentionAdapter(query: string) {
|
|
97
|
+
const [users, setUsers] = useState<{ id: string; name: string }[]>([]);
|
|
98
|
+
|
|
99
|
+
useEffect(() => {
|
|
100
|
+
if (!query) return;
|
|
101
|
+
let cancelled = false;
|
|
102
|
+
fetchUsers(query).then((results) => {
|
|
103
|
+
if (!cancelled) setUsers(results);
|
|
104
|
+
});
|
|
105
|
+
return () => { cancelled = true; };
|
|
106
|
+
}, [query]);
|
|
107
|
+
|
|
108
|
+
const adapter: Unstable_TriggerAdapter = useMemo(() => ({
|
|
109
|
+
categories: () => [],
|
|
110
|
+
categoryItems: () => [],
|
|
111
|
+
search: () =>
|
|
112
|
+
users.map((u) => ({ id: u.id, type: "user", label: u.name })),
|
|
113
|
+
}), [users]);
|
|
114
|
+
|
|
115
|
+
return adapter;
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
`query` here is the text the user typed after `@`. You can read it from `unstable_useTriggerPopoverScopeContext` if you need it inside the component tree, or pass it as state from a controlled input.
|
|
120
|
+
|
|
121
|
+
**With React Query:**
|
|
122
|
+
|
|
123
|
+
```tsx
|
|
124
|
+
import { useQuery } from "@tanstack/react-query";
|
|
125
|
+
import type { Unstable_TriggerAdapter } from "@assistant-ui/core";
|
|
126
|
+
|
|
127
|
+
function useMentionAdapter(query: string): Unstable_TriggerAdapter {
|
|
128
|
+
const { data = [] } = useQuery({
|
|
129
|
+
queryKey: ["mention-search", query],
|
|
130
|
+
queryFn: () => fetchUsers(query),
|
|
131
|
+
enabled: query.length > 0,
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
return useMemo(() => ({
|
|
135
|
+
categories: () => [],
|
|
136
|
+
categoryItems: () => [],
|
|
137
|
+
search: () =>
|
|
138
|
+
data.map((u) => ({ id: u.id, type: "user", label: u.name })),
|
|
139
|
+
}), [data]);
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
85
143
|
Pass the adapter to `TriggerPopover` and declare a `Directive` sub-primitive to bind the insertion behavior:
|
|
86
144
|
|
|
87
145
|
```tsx
|
|
@@ -333,27 +391,7 @@ import { LexicalComposerInput } from "@assistant-ui/react-lexical";
|
|
|
333
391
|
|
|
334
392
|
## Rendering Mentions in Messages
|
|
335
393
|
|
|
336
|
-
Use `DirectiveText` as the `Text` component for user messages so directives render as inline chips instead of raw syntax
|
|
337
|
-
|
|
338
|
-
```tsx
|
|
339
|
-
import { DirectiveText } from "@/components/assistant-ui/directive-text";
|
|
340
|
-
|
|
341
|
-
<MessagePrimitive.Parts
|
|
342
|
-
components={{
|
|
343
|
-
Text: DirectiveText,
|
|
344
|
-
}}
|
|
345
|
-
/>
|
|
346
|
-
```
|
|
347
|
-
|
|
348
|
-
For assistant messages, keep using your markdown renderer (e.g. `MarkdownText`) — the LLM typically does not emit directive syntax.
|
|
349
|
-
|
|
350
|
-
For a custom formatter, use `createDirectiveText`:
|
|
351
|
-
|
|
352
|
-
```tsx
|
|
353
|
-
import { createDirectiveText } from "@/components/assistant-ui/directive-text";
|
|
354
|
-
|
|
355
|
-
const MyDirectiveText = createDirectiveText(myFormatter);
|
|
356
|
-
```
|
|
394
|
+
Use `DirectiveText` as the `Text` component for user messages so directives render as inline chips instead of raw syntax. See the [Directive Text](/docs/ui/directive-text) guide for setup and customization.
|
|
357
395
|
|
|
358
396
|
## Processing Mentions on the Backend
|
|
359
397
|
|
|
@@ -467,74 +505,11 @@ Use the trigger popover primitives to build a fully custom popover:
|
|
|
467
505
|
|
|
468
506
|
### Primitives Reference
|
|
469
507
|
|
|
470
|
-
|
|
471
|
-
| --- | --- |
|
|
472
|
-
| `Unstable_TriggerPopoverRoot` | Root provider — groups one or more triggers, manages plugin registry |
|
|
473
|
-
| `Unstable_TriggerPopover` | Declares a trigger (id, char, adapter) and renders the popover container |
|
|
474
|
-
| `Unstable_TriggerPopover.Directive` | Behavior sub-primitive — inserts a formatted directive into the composer on selection |
|
|
475
|
-
| `Unstable_TriggerPopover.Action` | Behavior sub-primitive — runs a callback on selection; inserts a chip by default |
|
|
476
|
-
| `Unstable_TriggerPopoverCategories` | Render-function for the top-level category list |
|
|
477
|
-
| `Unstable_TriggerPopoverCategoryItem` | Button that drills into a category (`role="option"`, auto `data-highlighted`) |
|
|
478
|
-
| `Unstable_TriggerPopoverItems` | Render-function for items within the active category or search results |
|
|
479
|
-
| `Unstable_TriggerPopoverItem` | Button that selects an item (`role="option"`, auto `data-highlighted`) |
|
|
480
|
-
| `Unstable_TriggerPopoverBack` | Button that navigates back from items to categories |
|
|
481
|
-
|
|
482
|
-
See the [Composer API reference](/docs/api-reference/primitives/composer) for full prop details.
|
|
508
|
+
See the [Composer Primitives](/docs/primitives/composer) reference for the full list of trigger popover primitives and their props.
|
|
483
509
|
|
|
484
510
|
## Combining with Slash Commands
|
|
485
511
|
|
|
486
|
-
Mentions and
|
|
487
|
-
|
|
488
|
-
```tsx
|
|
489
|
-
<ComposerPrimitive.Unstable_TriggerPopoverRoot>
|
|
490
|
-
<ComposerPrimitive.Root>
|
|
491
|
-
<ComposerPrimitive.Input placeholder="Type @ to mention, / for commands..." />
|
|
492
|
-
<ComposerPrimitive.Send />
|
|
493
|
-
|
|
494
|
-
{/* Mention popover (shows on @) */}
|
|
495
|
-
<ComposerPrimitive.Unstable_TriggerPopover
|
|
496
|
-
char="@"
|
|
497
|
-
adapter={mention.adapter}
|
|
498
|
-
>
|
|
499
|
-
<ComposerPrimitive.Unstable_TriggerPopover.Directive {...mention.directive} />
|
|
500
|
-
<ComposerPrimitive.Unstable_TriggerPopoverCategories>
|
|
501
|
-
{(categories) => categories.map((cat) => (
|
|
502
|
-
<ComposerPrimitive.Unstable_TriggerPopoverCategoryItem key={cat.id} categoryId={cat.id}>
|
|
503
|
-
{cat.label}
|
|
504
|
-
</ComposerPrimitive.Unstable_TriggerPopoverCategoryItem>
|
|
505
|
-
))}
|
|
506
|
-
</ComposerPrimitive.Unstable_TriggerPopoverCategories>
|
|
507
|
-
<ComposerPrimitive.Unstable_TriggerPopoverItems>
|
|
508
|
-
{(items) => items.map((item) => (
|
|
509
|
-
<ComposerPrimitive.Unstable_TriggerPopoverItem key={item.id} item={item}>
|
|
510
|
-
{item.label}
|
|
511
|
-
</ComposerPrimitive.Unstable_TriggerPopoverItem>
|
|
512
|
-
))}
|
|
513
|
-
</ComposerPrimitive.Unstable_TriggerPopoverItems>
|
|
514
|
-
</ComposerPrimitive.Unstable_TriggerPopover>
|
|
515
|
-
|
|
516
|
-
{/* Slash command popover (shows on /) */}
|
|
517
|
-
<ComposerPrimitive.Unstable_TriggerPopover
|
|
518
|
-
char="/"
|
|
519
|
-
adapter={slashAdapter}
|
|
520
|
-
>
|
|
521
|
-
<ComposerPrimitive.Unstable_TriggerPopover.Action
|
|
522
|
-
formatter={unstable_defaultDirectiveFormatter}
|
|
523
|
-
onExecute={(item) => commandHandlers[item.id]?.()}
|
|
524
|
-
/>
|
|
525
|
-
<ComposerPrimitive.Unstable_TriggerPopoverItems>
|
|
526
|
-
{(items) => items.map((item, index) => (
|
|
527
|
-
<ComposerPrimitive.Unstable_TriggerPopoverItem key={item.id} item={item} index={index}>
|
|
528
|
-
{item.label}
|
|
529
|
-
</ComposerPrimitive.Unstable_TriggerPopoverItem>
|
|
530
|
-
))}
|
|
531
|
-
</ComposerPrimitive.Unstable_TriggerPopoverItems>
|
|
532
|
-
</ComposerPrimitive.Unstable_TriggerPopover>
|
|
533
|
-
</ComposerPrimitive.Root>
|
|
534
|
-
</ComposerPrimitive.Unstable_TriggerPopoverRoot>
|
|
535
|
-
```
|
|
536
|
-
|
|
537
|
-
Each `TriggerPopover` declares its own scope — its popover UI reads state only from that declaration, so `@` and `/` never collide.
|
|
512
|
+
Mentions and slash commands coexist on the same composer. See [Combining Slash Commands and Mentions](/docs/guides/slash-commands#combining-with-mentions) for the full pattern.
|
|
538
513
|
|
|
539
514
|
## Related
|
|
540
515
|
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Message Timing
|
|
3
3
|
description: Display stream timing metadata like duration, tokens per second, and time to first token.
|
|
4
|
+
platforms: ["react"]
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
Display stream performance metrics — duration, tokens per second, TTFT — on assistant messages.
|
|
7
8
|
|
|
9
|
+
<Callout type="warn">
|
|
10
|
+
This feature is experimental. The `useMessageTiming()` API and the set of tracked fields may change in future versions.
|
|
11
|
+
</Callout>
|
|
12
|
+
|
|
8
13
|
<Callout type="info">
|
|
9
14
|
The [`MessageTiming`](/docs/ui/message-timing) registry component provides a ready-made badge + popover UI. This guide covers the underlying `useMessageTiming()` hook for custom implementations and runtime-specific setup.
|
|
10
15
|
</Callout>
|
|
@@ -67,14 +72,15 @@ const AssistantMessage: FC = () => {
|
|
|
67
72
|
|
|
68
73
|
| Runtime | Supported | Notes |
|
|
69
74
|
|---------|:-:|-------|
|
|
70
|
-
|
|
|
75
|
+
| [Data Stream](/docs/runtimes/custom/data-stream) | Yes | Automatic via `AssistantMessageAccumulator` |
|
|
71
76
|
| AI SDK (`useChatRuntime`) | Yes | Automatic via client-side tracking |
|
|
72
77
|
| Local (`useLocalRuntime`) | Yes | Pass timing in `ChatModelRunResult.metadata` |
|
|
73
78
|
| ExternalStore | Yes | Pass timing in `ThreadMessageLike.metadata` |
|
|
74
79
|
| LangGraph | No | Not yet implemented |
|
|
75
80
|
| AG-UI | No | Not yet implemented |
|
|
81
|
+
| OpenCode | No | Not yet implemented |
|
|
76
82
|
|
|
77
|
-
###
|
|
83
|
+
### Data Stream
|
|
78
84
|
|
|
79
85
|
Timing is tracked automatically inside `AssistantMessageAccumulator`. No setup required.
|
|
80
86
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Multi-Agent
|
|
3
3
|
description: Render sub-agent conversations inside tool call UIs.
|
|
4
|
+
platforms: ["react"]
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
In a multi-agent (orchestrator) architecture, a main agent invokes sub-agents via tool calls. Each sub-agent may produce its own conversation (user/assistant messages, tool calls, etc.). assistant-ui supports rendering these nested conversations using the `MessagePartPrimitive.Messages` primitive.
|
|
@@ -51,7 +52,10 @@ const ResearchAgentToolUI = makeAssistantToolUI({
|
|
|
51
52
|
|
|
52
53
|
### Provide the Messages from the Backend
|
|
53
54
|
|
|
54
|
-
Your backend must populate the `messages` field on the tool call result.
|
|
55
|
+
Your backend must populate the `messages` field on the tool call result.
|
|
56
|
+
|
|
57
|
+
<Tabs items={["AI SDK", "LangGraph"]}>
|
|
58
|
+
<Tab value="AI SDK">
|
|
55
59
|
|
|
56
60
|
```ts title="api/chat/route.ts"
|
|
57
61
|
tools: {
|
|
@@ -62,7 +66,6 @@ tools: {
|
|
|
62
66
|
const subAgentMessages = await runResearcherAgent(query);
|
|
63
67
|
return {
|
|
64
68
|
answer: subAgentMessages.at(-1)?.content,
|
|
65
|
-
// The messages field is picked up by assistant-ui
|
|
66
69
|
messages: subAgentMessages,
|
|
67
70
|
};
|
|
68
71
|
},
|
|
@@ -70,9 +73,53 @@ tools: {
|
|
|
70
73
|
},
|
|
71
74
|
```
|
|
72
75
|
|
|
76
|
+
</Tab>
|
|
77
|
+
<Tab value="LangGraph">
|
|
78
|
+
|
|
79
|
+
With `@assistant-ui/react-langgraph`, use `unstable_createLangGraphStream` and set `unstable_allowCancellation: true` to wire up the stop button. When your graph runs a subgraph, the subgraph's messages appear on `ToolCallMessagePart.messages` automatically once you handle the `onSubgraphValues` / `onSubgraphUpdates` events.
|
|
80
|
+
|
|
81
|
+
```ts title="runtime.ts"
|
|
82
|
+
import {
|
|
83
|
+
useLangGraphRuntime,
|
|
84
|
+
unstable_createLangGraphStream,
|
|
85
|
+
} from "@assistant-ui/react-langgraph";
|
|
86
|
+
|
|
87
|
+
const runtime = useLangGraphRuntime({
|
|
88
|
+
unstable_allowCancellation: true,
|
|
89
|
+
stream: unstable_createLangGraphStream({
|
|
90
|
+
client,
|
|
91
|
+
assistantId,
|
|
92
|
+
// "custom" is required for generative UI; "updates" for subgraph events
|
|
93
|
+
streamMode: ["messages", "updates", "custom"],
|
|
94
|
+
// abort the run server-side when the user clicks stop
|
|
95
|
+
onDisconnect: "cancel",
|
|
96
|
+
}),
|
|
97
|
+
eventHandlers: {
|
|
98
|
+
onSubgraphValues: (namespace, values) => {
|
|
99
|
+
// namespace = e.g. "tools:call_abc" — the sub-agent's node path
|
|
100
|
+
// values contains the subgraph state, including its messages array
|
|
101
|
+
},
|
|
102
|
+
onSubgraphUpdates: (namespace, updates) => {
|
|
103
|
+
// incremental state updates from the subgraph
|
|
104
|
+
},
|
|
105
|
+
onSubgraphError: (namespace, error) => {
|
|
106
|
+
// error scoped to the subgraph; does not mark the parent message failed
|
|
107
|
+
},
|
|
108
|
+
onMessageChunk: (chunk, metadata) => {
|
|
109
|
+
// metadata.namespace is set when the chunk originates from a subgraph
|
|
110
|
+
// use it to attribute the chunk to the correct sub-agent
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
See [LangGraph Streaming](/docs/runtimes/langgraph/streaming) for the full event handler reference.
|
|
117
|
+
|
|
118
|
+
</Tab>
|
|
119
|
+
</Tabs>
|
|
120
|
+
|
|
73
121
|
<Callout type="info">
|
|
74
|
-
The
|
|
75
|
-
framework. The key requirement is that the tool result's corresponding
|
|
122
|
+
The key requirement is that the tool result's corresponding
|
|
76
123
|
`ToolCallMessagePart` includes a `messages` array of `ThreadMessage` objects.
|
|
77
124
|
</Callout>
|
|
78
125
|
|
|
@@ -95,6 +142,17 @@ function App() {
|
|
|
95
142
|
</Step>
|
|
96
143
|
</Steps>
|
|
97
144
|
|
|
145
|
+
## Subgraph Namespace Events
|
|
146
|
+
|
|
147
|
+
When using LangGraph, subgraph events carry a `namespace` that identifies which sub-agent emitted them. This lets you attribute messages and state to specific sub-agents without polling or manual coordination.
|
|
148
|
+
|
|
149
|
+
- `onSubgraphValues(namespace, values)` fires when a subgraph emits a full state snapshot. Use the `values.messages` array to populate `ToolCallMessagePart.messages` for that sub-agent.
|
|
150
|
+
- `onSubgraphUpdates(namespace, updates)` fires for incremental state patches from a subgraph.
|
|
151
|
+
- `onSubgraphError(namespace, error)` fires when a subgraph fails. The parent message is not marked incomplete; only top-level errors trigger that.
|
|
152
|
+
- `onMessageChunk(chunk, metadata)` includes `metadata.namespace` when the chunk originates from a subgraph. Use this to display per-sub-agent streaming indicators.
|
|
153
|
+
|
|
154
|
+
The `namespace` value mirrors the pipe-separated suffix on the LangGraph event name (e.g. `values|tools:call_abc` gives `"tools:call_abc"`).
|
|
155
|
+
|
|
98
156
|
## Recursive Sub-Agents
|
|
99
157
|
|
|
100
158
|
If a sub-agent's tool calls also have nested messages, the same pattern applies recursively:
|
|
@@ -172,3 +230,5 @@ function SubConversation({
|
|
|
172
230
|
- [Generative UI](/docs/guides/tool-ui) — Creating tool call UIs
|
|
173
231
|
- [MessagePartPrimitive](/docs/api-reference/primitives/message-part) — API reference for message part primitives
|
|
174
232
|
- [Sub-Agent Model Tracking](/docs/cloud/ai-sdk#sub-agent-model-tracking) — Track delegated model usage and costs in the Cloud dashboard
|
|
233
|
+
- [LangGraph Streaming](/docs/runtimes/langgraph/streaming) — Event handlers, subgraph events, and message metadata
|
|
234
|
+
- [LangGraph Generative UI](/docs/runtimes/langgraph/generative-ui) — Structured UI components emitted by your graph
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Quote Selected Text
|
|
3
3
|
description: Let users select and quote text from messages. Full guide including backend handling and programmatic API.
|
|
4
|
+
platforms: ["react"]
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
import { QuoteComposerSample } from "@/components/docs/samples/quote-composer";
|
|
@@ -9,17 +10,11 @@ import { QuoteComposerSample } from "@/components/docs/samples/quote-composer";
|
|
|
9
10
|
|
|
10
11
|
## Get Started
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
Install and wire up the `quote` registry component by following the [Quote component page](/docs/ui/quote). It covers the install command, component placement, and the `injectQuoteContext` helper for forwarding quote data to the LLM.
|
|
13
14
|
|
|
14
|
-
<
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
- **QuoteBlock** renders quoted text inline in user messages
|
|
19
|
-
- **SelectionToolbar** is a floating toolbar that appears on text selection
|
|
20
|
-
- **ComposerQuotePreview** shows the pending quote inside the composer
|
|
21
|
-
|
|
22
|
-
See the [Quote component page](/docs/ui/quote) for full setup steps and API reference.
|
|
15
|
+
<Callout type="warn">
|
|
16
|
+
**Limitations:** only one quote can be active at a time. `setQuote` replaces the previous quote instead of appending. The floating toolbar only appears when the selection is entirely within a single message part; cross-message and cross-part selections are ignored.
|
|
17
|
+
</Callout>
|
|
23
18
|
|
|
24
19
|
---
|
|
25
20
|
|
|
@@ -132,7 +127,7 @@ function CustomQuoteDisplay() {
|
|
|
132
127
|
|
|
133
128
|
## Programmatic API
|
|
134
129
|
|
|
135
|
-
Set or clear quotes via
|
|
130
|
+
Set or clear quotes via `useAui` from `@assistant-ui/react`. Call `aui.thread().composer().setQuote()` when your component is rendered outside of a specific thread context, or `aui.composer().setQuote()` when it is rendered inside a thread:
|
|
136
131
|
|
|
137
132
|
```tsx
|
|
138
133
|
import { useAui } from "@assistant-ui/react";
|
|
@@ -162,12 +157,10 @@ function MyComponent() {
|
|
|
162
157
|
|
|
163
158
|
## Design Notes
|
|
164
159
|
|
|
165
|
-
- **
|
|
166
|
-
- **
|
|
167
|
-
-
|
|
168
|
-
- **
|
|
169
|
-
- **`isEmpty` unchanged:** A quote by itself does not make the composer non-empty. The user still needs to type a reply.
|
|
170
|
-
- **Scroll hides toolbar:** The toolbar hides on scroll because its position would otherwise become stale.
|
|
160
|
+
- **snapshot text:** the selected text is captured when the quote is created and is not linked to the source message afterward.
|
|
161
|
+
- **streaming messages:** the toolbar still works while a message is streaming because it relies on the captured selection rather than message status.
|
|
162
|
+
- **`isEmpty` unchanged:** a quote by itself does not make the composer non-empty; the user still needs to type a reply.
|
|
163
|
+
- **scroll hides toolbar:** the toolbar hides on scroll because its position would otherwise become stale.
|
|
171
164
|
|
|
172
165
|
## Related
|
|
173
166
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Slash Commands
|
|
3
3
|
description: Let users type / in the composer to trigger predefined actions from a popover picker.
|
|
4
|
+
platforms: ["react"]
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
Slash commands let users type `/` in the composer to open a popover, browse available commands, and execute one. Unlike [mentions](/docs/guides/mentions) (which only insert a directive into the message), slash commands additionally fire an **action callback** at the moment of selection.
|
|
@@ -89,6 +90,17 @@ function MyComposer() {
|
|
|
89
90
|
|
|
90
91
|
The label defaults to `/${id}`; override via `label` on the command. Icons are strings that your `iconMap` on the picker UI resolves to components (see [ComposerTriggerPopover](/docs/ui/composer-trigger-popover)).
|
|
91
92
|
|
|
93
|
+
### `unstable_useSlashCommandAdapter` options
|
|
94
|
+
|
|
95
|
+
| Option | Type | Default | Description |
|
|
96
|
+
| --- | --- | --- | --- |
|
|
97
|
+
| `commands` | `Unstable_SlashCommand[]` | — | Command definitions — each has `id`, optional `label`, `description`, `icon`, and an `execute` callback (required) |
|
|
98
|
+
| `removeOnExecute` | `boolean` | `false` | When `true`, strips the trigger text from the composer after executing instead of leaving a directive chip |
|
|
99
|
+
| `iconMap` | `Record<string, IconComponent>` | — | Maps `metadata.icon` / category `id` strings to React icon components; forwarded to `ComposerTriggerPopover` |
|
|
100
|
+
| `fallbackIcon` | `IconComponent` | — | Fallback when no `iconMap` entry matches; forwarded to `ComposerTriggerPopover` |
|
|
101
|
+
|
|
102
|
+
The hook returns `{ adapter, action, iconMap?, fallbackIcon? }` — spread directly into `<ComposerTriggerPopover char="/" {...slash} />` for one-line wiring.
|
|
103
|
+
|
|
92
104
|
### 2. Controlling the Chip
|
|
93
105
|
|
|
94
106
|
By default, a selected `/summarize` is converted into a directive chip (`:command[/summarize]{name=summarize}`) in the composer text and the command's `execute` fires. This keeps an audit trail of which commands were invoked.
|
|
@@ -236,57 +248,111 @@ Slash commands and mentions live under the same `TriggerPopoverRoot`. Declare on
|
|
|
236
248
|
|
|
237
249
|
Each `TriggerPopover` is its own scope — the `@` popover and the `/` popover read state from their own declaration and never collide. Keyboard events route to whichever popover is currently active.
|
|
238
250
|
|
|
239
|
-
##
|
|
251
|
+
## Commands with Arguments
|
|
252
|
+
|
|
253
|
+
Some commands accept inline arguments typed after the command word — for example `/translate en` or `/ask what is TypeScript`. Because the adapter's `search` method receives the full text after `/`, you can split on the first space to separate the command from its arguments:
|
|
240
254
|
|
|
241
|
-
|
|
255
|
+
```tsx
|
|
256
|
+
const SLASH_COMMANDS: readonly Unstable_SlashCommand[] = [
|
|
257
|
+
{
|
|
258
|
+
id: "translate",
|
|
259
|
+
description: "Translate to a language, e.g. /translate en",
|
|
260
|
+
execute: () => {/* arguments extracted separately, see below */},
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
id: "ask",
|
|
264
|
+
description: "Ask about a topic, e.g. /ask what is TypeScript",
|
|
265
|
+
execute: () => {/* arguments extracted separately, see below */},
|
|
266
|
+
},
|
|
267
|
+
];
|
|
242
268
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
269
|
+
function MyComposer() {
|
|
270
|
+
const composerRef = useRef<HTMLTextAreaElement>(null);
|
|
271
|
+
const slash = unstable_useSlashCommandAdapter({
|
|
272
|
+
commands: SLASH_COMMANDS.map((cmd) => ({
|
|
273
|
+
...cmd,
|
|
274
|
+
execute: () => {
|
|
275
|
+
// Read the full composer text to extract arguments
|
|
276
|
+
const raw = composerRef.current?.value ?? "";
|
|
277
|
+
// Match "/<id> <args>" at start of input
|
|
278
|
+
const match = raw.match(new RegExp(`^\\/${cmd.id}\\s+(.*)`));
|
|
279
|
+
const args = match?.[1]?.trim() ?? "";
|
|
280
|
+
handleCommand(cmd.id, args);
|
|
281
|
+
},
|
|
282
|
+
})),
|
|
283
|
+
removeOnExecute: true,
|
|
284
|
+
});
|
|
250
285
|
|
|
251
|
-
|
|
286
|
+
return (
|
|
287
|
+
<ComposerPrimitive.Unstable_TriggerPopoverRoot>
|
|
288
|
+
<ComposerPrimitive.Root>
|
|
289
|
+
<ComposerPrimitive.Input ref={composerRef} placeholder="Type / for commands..." />
|
|
290
|
+
<ComposerPrimitive.Unstable_TriggerPopover char="/" adapter={slash.adapter}>
|
|
291
|
+
<ComposerPrimitive.Unstable_TriggerPopover.Action {...slash.action} />
|
|
292
|
+
<ComposerPrimitive.Unstable_TriggerPopoverItems>
|
|
293
|
+
{(items) => items.map((item, i) => (
|
|
294
|
+
<ComposerPrimitive.Unstable_TriggerPopoverItem key={item.id} item={item} index={i}>
|
|
295
|
+
<strong>{item.label}</strong>
|
|
296
|
+
{item.description && <span>{item.description}</span>}
|
|
297
|
+
</ComposerPrimitive.Unstable_TriggerPopoverItem>
|
|
298
|
+
))}
|
|
299
|
+
</ComposerPrimitive.Unstable_TriggerPopoverItems>
|
|
300
|
+
</ComposerPrimitive.Unstable_TriggerPopover>
|
|
301
|
+
<ComposerPrimitive.Send>Send</ComposerPrimitive.Send>
|
|
302
|
+
</ComposerPrimitive.Root>
|
|
303
|
+
</ComposerPrimitive.Unstable_TriggerPopoverRoot>
|
|
304
|
+
);
|
|
305
|
+
}
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
`removeOnExecute: true` strips the `/translate en` text from the composer so the argument is consumed by the handler rather than sent to the LLM.
|
|
309
|
+
|
|
310
|
+
## Async Command Loading
|
|
252
311
|
|
|
253
|
-
|
|
312
|
+
The adapter interface is synchronous, but the command list can come from any async source. Load commands into state (or a query cache) and pass the current snapshot to the hook. Because `unstable_useSlashCommandAdapter` re-runs on every render, the adapter always reflects the latest list.
|
|
254
313
|
|
|
255
|
-
|
|
256
|
-
- `ComposerPrimitive.Unstable_TriggerPopover` — declares one trigger (id, char, adapter) and renders its popover container
|
|
257
|
-
- Behavior sub-primitives — exactly one per `TriggerPopover`:
|
|
258
|
-
- `Unstable_TriggerPopover.Directive` — writes a formatted directive on selection ("mention" path)
|
|
259
|
-
- `Unstable_TriggerPopover.Action` — fires a callback on selection ("slash" path); inserts a chip by default, strip with `removeOnExecute`
|
|
260
|
-
- Shared sub-primitives (`TriggerPopoverCategories`, `TriggerPopoverItems`, `TriggerPopoverBack`) live inside a `TriggerPopover`
|
|
314
|
+
**With React state:**
|
|
261
315
|
|
|
262
|
-
|
|
316
|
+
```tsx
|
|
317
|
+
function MyComposer() {
|
|
318
|
+
const [commands, setCommands] = useState<Unstable_SlashCommand[]>([]);
|
|
263
319
|
|
|
264
|
-
|
|
320
|
+
useEffect(() => {
|
|
321
|
+
fetchAvailableCommands().then(setCommands);
|
|
322
|
+
}, []);
|
|
265
323
|
|
|
266
|
-
|
|
324
|
+
const slash = unstable_useSlashCommandAdapter({ commands });
|
|
267
325
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
326
|
+
return (/* ... */);
|
|
327
|
+
}
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
**With React Query:**
|
|
331
|
+
|
|
332
|
+
```tsx
|
|
333
|
+
function MyComposer() {
|
|
334
|
+
const { data: commands = [] } = useQuery({
|
|
335
|
+
queryKey: ["slash-commands"],
|
|
336
|
+
queryFn: fetchAvailableCommands,
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
const slash = unstable_useSlashCommandAdapter({ commands });
|
|
340
|
+
|
|
341
|
+
return (/* ... */);
|
|
342
|
+
}
|
|
273
343
|
```
|
|
274
344
|
|
|
275
|
-
|
|
345
|
+
## Keyboard Navigation
|
|
346
|
+
|
|
347
|
+
See [ComposerTriggerPopover keyboard navigation](/docs/ui/composer-trigger-popover#keyboard-navigation) for the full key bindings table.
|
|
348
|
+
|
|
349
|
+
## Trigger Popover Architecture
|
|
350
|
+
|
|
351
|
+
Both mentions and slash commands are built on a generic trigger popover system where each `Unstable_TriggerPopover` declares one trigger character, an adapter, and exactly one behavior sub-primitive (`Directive` or `Action`). Multiple triggers coexist under a single `Unstable_TriggerPopoverRoot`. See the [Composer Primitives](/docs/primitives/composer) reference for the complete API.
|
|
276
352
|
|
|
277
353
|
## Primitives Reference
|
|
278
354
|
|
|
279
|
-
|
|
280
|
-
| --- | --- |
|
|
281
|
-
| `Unstable_TriggerPopoverRoot` | Root — groups triggers, provides input plugin registry |
|
|
282
|
-
| `Unstable_TriggerPopover` | Declares a trigger and renders its popover container |
|
|
283
|
-
| `Unstable_TriggerPopover.Directive` | Behavior sub-primitive — inserts a formatted directive on selection |
|
|
284
|
-
| `Unstable_TriggerPopover.Action` | Behavior sub-primitive — runs `onExecute` on selection; chip-by-default |
|
|
285
|
-
| `Unstable_TriggerPopoverCategories` | Render-function for the top-level category list |
|
|
286
|
-
| `Unstable_TriggerPopoverCategoryItem` | Button that drills into a category (`role="option"`, auto `data-highlighted`) |
|
|
287
|
-
| `Unstable_TriggerPopoverItems` | Render-function for items within the active category or search results |
|
|
288
|
-
| `Unstable_TriggerPopoverItem` | Button that selects an item (`role="option"`, auto `data-highlighted`) |
|
|
289
|
-
| `Unstable_TriggerPopoverBack` | Button that navigates back from items to categories |
|
|
355
|
+
See the [Composer Primitives](/docs/primitives/composer) reference for the full list of trigger popover primitives and their props.
|
|
290
356
|
|
|
291
357
|
## Related
|
|
292
358
|
|