@assistant-ui/mcp-docs-server 0.1.33 → 0.1.35

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 (102) hide show
  1. package/.docs/organized/code-examples/waterfall.md +7 -7
  2. package/.docs/organized/code-examples/with-a2a.md +8 -8
  3. package/.docs/organized/code-examples/with-ag-ui.md +12 -12
  4. package/.docs/organized/code-examples/with-ai-sdk-v6.md +10 -10
  5. package/.docs/organized/code-examples/with-artifacts.md +40 -34
  6. package/.docs/organized/code-examples/with-assistant-transport.md +11 -11
  7. package/.docs/organized/code-examples/with-browser-extension.md +9 -9
  8. package/.docs/organized/code-examples/with-chain-of-thought.md +72 -51
  9. package/.docs/organized/code-examples/with-cloud-standalone.md +10 -10
  10. package/.docs/organized/code-examples/with-cloud.md +10 -10
  11. package/.docs/organized/code-examples/with-custom-thread-list.md +10 -10
  12. package/.docs/organized/code-examples/with-elevenlabs-conversational.md +12 -12
  13. package/.docs/organized/code-examples/with-elevenlabs-scribe.md +12 -12
  14. package/.docs/organized/code-examples/with-expo.md +66 -31
  15. package/.docs/organized/code-examples/with-external-store.md +8 -8
  16. package/.docs/organized/code-examples/with-ffmpeg.md +13 -13
  17. package/.docs/organized/code-examples/with-generative-ui.md +98 -368
  18. package/.docs/organized/code-examples/with-google-adk.md +9 -9
  19. package/.docs/organized/code-examples/with-heat-graph.md +7 -7
  20. package/.docs/organized/code-examples/with-image-generation.md +10 -10
  21. package/.docs/organized/code-examples/with-interactables.md +10 -10
  22. package/.docs/organized/code-examples/with-langchain.md +10 -10
  23. package/.docs/organized/code-examples/with-langgraph.md +33 -29
  24. package/.docs/organized/code-examples/with-livekit.md +12 -12
  25. package/.docs/organized/code-examples/with-mcp.md +11 -11
  26. package/.docs/organized/code-examples/with-opencode.md +109 -583
  27. package/.docs/organized/code-examples/with-pi.md +2044 -0
  28. package/.docs/organized/code-examples/with-react-hook-form.md +11 -11
  29. package/.docs/organized/code-examples/with-react-ink-web.md +691 -0
  30. package/.docs/organized/code-examples/with-react-ink.md +309 -102
  31. package/.docs/organized/code-examples/with-react-router.md +14 -14
  32. package/.docs/organized/code-examples/with-resumable-stream.md +11 -11
  33. package/.docs/organized/code-examples/with-store.md +70 -66
  34. package/.docs/organized/code-examples/with-tanstack.md +25 -11
  35. package/.docs/organized/code-examples/with-tap-runtime.md +8 -8
  36. package/.docs/organized/code-examples/with-virtualized-thread.md +656 -0
  37. package/.docs/raw/docs/(docs)/architecture.mdx +65 -53
  38. package/.docs/raw/docs/(reference)/api-reference/external-store/message-conversion.mdx +1 -1
  39. package/.docs/raw/docs/(reference)/api-reference/external-store/runtime.mdx +3 -0
  40. package/.docs/raw/docs/(reference)/api-reference/hooks/primitives.mdx +44 -1
  41. package/.docs/raw/docs/(reference)/api-reference/integrations/react-ai-sdk.mdx +14 -3
  42. package/.docs/raw/docs/(reference)/api-reference/model-context/context.mdx +1 -1
  43. package/.docs/raw/docs/(reference)/api-reference/tools/rendering.mdx +2 -23
  44. package/.docs/raw/docs/(reference)/api-reference/tools/status.mdx +22 -0
  45. package/.docs/raw/docs/(reference)/api-reference/tools/toolkits.mdx +93 -9
  46. package/.docs/raw/docs/(reference)/api-reference/utilities/miscellaneous.mdx +21 -86
  47. package/.docs/raw/docs/guides/chain-of-thought.mdx +1 -1
  48. package/.docs/raw/docs/guides/index.mdx +3 -0
  49. package/.docs/raw/docs/guides/input-history.mdx +55 -0
  50. package/.docs/raw/docs/guides/virtualization.mdx +63 -0
  51. package/.docs/raw/docs/ink/adapters.mdx +23 -1
  52. package/.docs/raw/docs/ink/hooks.mdx +22 -19
  53. package/.docs/raw/docs/migrations/toolkit-tools.mdx +14 -8
  54. package/.docs/raw/docs/react-native/hooks.mdx +26 -18
  55. package/.docs/raw/docs/runtimes/ag-ui/runtime-options.mdx +39 -0
  56. package/.docs/raw/docs/runtimes/ai-sdk/v6.mdx +3 -3
  57. package/.docs/raw/docs/runtimes/concepts/architecture.mdx +46 -4
  58. package/.docs/raw/docs/runtimes/concepts/stability.mdx +1 -1
  59. package/.docs/raw/docs/runtimes/custom/assistant-transport.mdx +54 -12
  60. package/.docs/raw/docs/runtimes/custom/data-stream.mdx +1 -1
  61. package/.docs/raw/docs/runtimes/custom/external-store.mdx +62 -4
  62. package/.docs/raw/docs/runtimes/custom/local-runtime.mdx +120 -4
  63. package/.docs/raw/docs/runtimes/google-adk/hooks.mdx +9 -9
  64. package/.docs/raw/docs/runtimes/langgraph/streaming.mdx +13 -0
  65. package/.docs/raw/docs/runtimes/langgraph/tutorial/part-2.mdx +5 -5
  66. package/.docs/raw/docs/runtimes/langgraph/tutorial/part-3.mdx +3 -3
  67. package/.docs/raw/docs/runtimes/pick-a-runtime.mdx +6 -6
  68. package/.docs/raw/docs/tools/backend.mdx +19 -11
  69. package/.docs/raw/docs/tools/defining-tools.mdx +177 -52
  70. package/.docs/raw/docs/tools/index.mdx +7 -12
  71. package/.docs/raw/docs/tools/mcp.mdx +83 -15
  72. package/.docs/raw/docs/tools/multi-agent.mdx +5 -5
  73. package/.docs/raw/docs/tools/tool-ui.mdx +64 -28
  74. package/.docs/raw/docs/tools/user-managed-mcp.mdx +4 -4
  75. package/.docs/raw/docs/ui/dot-matrix.mdx +133 -0
  76. package/.docs/raw/docs/ui/mermaid.mdx +16 -9
  77. package/.docs/raw/docs/ui/model-selector.mdx +219 -52
  78. package/.docs/raw/docs/ui/number-roll.mdx +154 -0
  79. package/.docs/raw/docs/ui/part-grouping.mdx +2 -2
  80. package/.docs/raw/docs/ui/reasoning.mdx +3 -3
  81. package/.docs/raw/docs/ui/streamdown.mdx +2 -0
  82. package/.docs/raw/docs/ui/syntax-highlighting.mdx +1 -1
  83. package/.docs/raw/docs/ui/thread.mdx +52 -0
  84. package/.docs/raw/docs/ui/tool-fallback.mdx +16 -0
  85. package/.docs/raw/docs/utilities/react-o11y.mdx +2 -2
  86. package/dist/constants.js.map +1 -1
  87. package/dist/index.js.map +1 -1
  88. package/dist/prepare-docs/code-examples.js.map +1 -1
  89. package/dist/prepare-docs/copy-raw.js.map +1 -1
  90. package/dist/prepare-docs/prepare.js.map +1 -1
  91. package/dist/stdio.js.map +1 -1
  92. package/dist/tools/docs.js.map +1 -1
  93. package/dist/tools/examples.js.map +1 -1
  94. package/dist/tools/tests/test-setup.js.map +1 -1
  95. package/dist/utils/mdx.js.map +1 -1
  96. package/dist/utils/paths.js.map +1 -1
  97. package/package.json +4 -4
  98. /package/.docs/raw/docs/{(docs)/copilots → copilots}/assistant-frame.mdx +0 -0
  99. /package/.docs/raw/docs/{(docs)/copilots → copilots}/make-assistant-visible.mdx +0 -0
  100. /package/.docs/raw/docs/{(docs)/copilots → copilots}/model-context.mdx +0 -0
  101. /package/.docs/raw/docs/{(docs)/copilots → copilots}/motivation.mdx +0 -0
  102. /package/.docs/raw/docs/{(docs)/copilots → copilots}/use-assistant-instructions.mdx +0 -0
@@ -96,14 +96,14 @@ Learn more about creating tools in the [Tools Guide](/docs/tools/defining-tools)
96
96
  If your tool is defined elsewhere (e.g., in your backend API, MCP server, or LangGraph), register a backend toolkit entry with just `render`:
97
97
 
98
98
  ```tsx
99
- const toolkit = {
99
+ const toolkit = defineToolkit({
100
100
  getWeather: {
101
101
  type: "backend",
102
102
  render: ({ args, result, status }) => {
103
103
  // UI rendering logic only
104
104
  },
105
105
  },
106
- } satisfies Toolkit;
106
+ });
107
107
  ```
108
108
 
109
109
  ## Quick Start Example
@@ -180,12 +180,12 @@ const WeatherToolUI: ToolCallMessagePartComponent<
180
180
  Put the renderer on the matching backend toolkit entry:
181
181
 
182
182
  ```tsx
183
- const toolkit = {
183
+ const toolkit = defineToolkit({
184
184
  getWeather: {
185
185
  type: "backend",
186
186
  render: WeatherToolUI,
187
187
  },
188
- } satisfies Toolkit;
188
+ });
189
189
 
190
190
  function App({ runtime }: { runtime: AssistantRuntime }) {
191
191
  const aui = useAui({ tools: Tools({ toolkit }) });
@@ -286,12 +286,12 @@ export const WebSearchToolUI: ToolCallMessagePartComponent<
286
286
  Register it on the toolkit:
287
287
 
288
288
  ```tsx
289
- const toolkit = {
289
+ const toolkit = defineToolkit({
290
290
  webSearch: {
291
291
  type: "backend",
292
292
  render: WebSearchToolUI,
293
293
  },
294
- } satisfies Toolkit;
294
+ });
295
295
  ```
296
296
 
297
297
  ### Dynamic Toolkit Pattern
@@ -301,7 +301,7 @@ Use a toolkit hook in its own file when the renderer needs component state:
301
301
  ```tsx title="analyze-data-toolkit.tsx"
302
302
  "use client";
303
303
 
304
- import { type Toolkit, useInlineRender } from "@assistant-ui/react";
304
+ import { defineToolkit, useInlineRender } from "@assistant-ui/react";
305
305
  import { useMemo } from "react";
306
306
 
307
307
  export function useAnalyzeDataToolkit(theme: "light" | "dark") {
@@ -317,12 +317,12 @@ export function useAnalyzeDataToolkit(theme: "light" | "dark") {
317
317
 
318
318
  return useMemo(
319
319
  () =>
320
- ({
320
+ defineToolkit({
321
321
  analyzeData: {
322
322
  type: "backend",
323
323
  render: renderAnalyzeData,
324
324
  },
325
- }) satisfies Toolkit,
325
+ }),
326
326
  [renderAnalyzeData],
327
327
  );
328
328
  }
@@ -358,7 +358,7 @@ For tools that need access to parent component props:
358
358
  ```tsx title="inventory-toolkit.tsx"
359
359
  "use client";
360
360
 
361
- import { type Toolkit, useInlineRender } from "@assistant-ui/react";
361
+ import { defineToolkit, useInlineRender } from "@assistant-ui/react";
362
362
  import { useMemo } from "react";
363
363
 
364
364
  export function useInventoryToolkit(productId: string, productName: string) {
@@ -376,12 +376,12 @@ export function useInventoryToolkit(productId: string, productName: string) {
376
376
 
377
377
  return useMemo(
378
378
  () =>
379
- ({
379
+ defineToolkit({
380
380
  checkInventory: {
381
381
  type: "backend",
382
382
  render: renderInventory,
383
383
  },
384
- }) satisfies Toolkit,
384
+ }),
385
385
  [renderInventory],
386
386
  );
387
387
  }
@@ -419,7 +419,7 @@ Create tools that collect user input during execution:
419
419
  </Callout>
420
420
 
421
421
  ```tsx
422
- const toolkit = {
422
+ const toolkit = defineToolkit({
423
423
  selectDate: {
424
424
  type: "human",
425
425
  description: "Ask the user to select a date.",
@@ -445,7 +445,7 @@ const toolkit = {
445
445
  );
446
446
  },
447
447
  },
448
- } satisfies Toolkit;
448
+ });
449
449
  ```
450
450
 
451
451
  ### Multi-Step Interactions
@@ -540,7 +540,7 @@ export default defineToolkit({
540
540
  Some runtimes (notably AI SDK v6's `needsApproval` tools) pause on the server and emit an approval request that the client must acknowledge before the tool runs. assistant-ui surfaces this on the tool part as `approval` and exposes `respondToApproval({ approved, reason? })` on the renderer:
541
541
 
542
542
  ```tsx
543
- const toolkit = {
543
+ const toolkit = defineToolkit({
544
544
  deploy: {
545
545
  type: "backend",
546
546
  render: ({ args, approval, respondToApproval, result }) => {
@@ -570,19 +570,55 @@ const toolkit = {
570
570
  return <p>Deployed</p>;
571
571
  },
572
572
  },
573
- } satisfies Toolkit;
573
+ });
574
574
  ```
575
575
 
576
576
  `approval.approved` is a three-state signal:
577
577
 
578
578
  - `undefined`: gate is open, the renderer should ask the user. This is the only state in which `respondToApproval` is legal.
579
579
  - `true`: decision recorded as allow. The server is producing the result (or has produced one, available on `result`).
580
- - `false`: decision recorded as deny. `output-denied` from the runtime sets `isError` and exposes `approval.reason`.
580
+ - `false`: decision recorded as deny. The runtime records an error result (`isError`) and exposes `approval.reason`.
581
581
 
582
582
  `approval.isAutomatic` is `true` when the runtime granted the decision from a server-side policy rather than the user; render a "auto-approved" badge instead of buttons in that case.
583
583
 
584
+ Approval gates require a runtime that implements them: the AI SDK v6 runtime emits them for `needsApproval` tools, and `LocalRuntime` supports gates emitted by your `ChatModelAdapter`; see [LocalRuntime approval gates](/docs/runtimes/custom/local-runtime#approval-gates). For tools where the user supplies the result itself, use `unstable_humanToolNames` with `addResult` instead; see [human-in-the-loop tools](/docs/runtimes/custom/local-runtime#human-in-the-loop-tools).
585
+
584
586
  For the wire-side setup (`needsApproval`, `sendAutomaticallyWhen`), see [AI SDK v6 server-side tool approval](/docs/runtimes/ai-sdk/v6#server-side-tool-approval).
585
587
 
588
+ ### Approval options
589
+
590
+ Beyond the plain allow / deny pair, the host can attach a list of decision options to an approval, for example "allow once", "allow for this session", and "always allow". Each option carries a machine-readable `kind` (`"allow-once"`, `"allow-always"`, `"reject-once"`, `"reject-always"`); scope semantics like session versus global belong to the option's `id` and `label`, which only the host interprets:
591
+
592
+ ```ts
593
+ const approval = {
594
+ id: "a1",
595
+ options: [
596
+ { id: "once", kind: "allow-once" },
597
+ { id: "session", kind: "allow-always", label: "Allow for this session" },
598
+ {
599
+ id: "always",
600
+ kind: "allow-always",
601
+ label: "Always allow",
602
+ grants: ["git *"],
603
+ confirm: true,
604
+ },
605
+ { id: "deny", kind: "reject-once" },
606
+ ],
607
+ };
608
+ ```
609
+
610
+ Renderers respond with the chosen option instead of a boolean; the option's kind resolves the decision:
611
+
612
+ ```tsx
613
+ respondToApproval({ optionId: "session" });
614
+ ```
615
+
616
+ The runtime receives `{ approvalId, approved, optionId, reason? }`, so a host that persists "always allow" decisions can key its store off `optionId`. Persistence is entirely host-owned: assistant-ui never stores a decision and never auto-answers future approvals. `grants` lists the patterns an option would persist (shown to the user before they commit), and `confirm` opts the option into a confirmation step. Options with custom `_`-prefixed kinds are skipped by the default `ToolFallback` bar and must be answered with an explicit `approved` value, optionally alongside the `optionId` so the chosen option is still recorded.
617
+
618
+ Approvals that end without a decision (a cancelled run or an expired request) are recorded by the host as `approval.resolution: "cancelled" | "expired"`, which closes the gate without recording a deny.
619
+
620
+ The default `ToolFallback` component renders supplied options automatically, including the confirmation step.
621
+
586
622
  ## Advanced Features
587
623
 
588
624
  ### Tool Status Handling
@@ -626,7 +662,7 @@ Sometimes you want to capture a tool call's streaming arguments but only render
626
662
  Return `null` from the tool UI's `render` until `status.type === "complete"`. The streaming args still arrive in `args` as the model emits them, you just ignore them until the call is done:
627
663
 
628
664
  ```tsx
629
- const toolkit = {
665
+ const toolkit = defineToolkit({
630
666
  renderChart: {
631
667
  type: "backend",
632
668
  render: ({ args, status }) => {
@@ -634,7 +670,7 @@ const toolkit = {
634
670
  return <Chart title={args.title} data={args.series} />;
635
671
  },
636
672
  },
637
- } satisfies Toolkit;
673
+ });
638
674
  ```
639
675
 
640
676
  The chart mounts once, with the final args, after streaming finishes. No re-renders during the stream.
@@ -682,7 +718,7 @@ Use `useToolArgsStatus` to react to per-field streaming state. The hook returns
682
718
  ```tsx
683
719
  import { useToolArgsStatus } from "@assistant-ui/react";
684
720
 
685
- const toolkit = {
721
+ const toolkit = defineToolkit({
686
722
  submitForm: {
687
723
  type: "backend",
688
724
  render: ({ args }) => {
@@ -714,7 +750,7 @@ const toolkit = {
714
750
  );
715
751
  },
716
752
  },
717
- } satisfies Toolkit;
753
+ });
718
754
  ```
719
755
 
720
756
  ### Partial Results & Streaming
@@ -722,7 +758,7 @@ const toolkit = {
722
758
  Display results as they stream in:
723
759
 
724
760
  ```tsx
725
- const toolkit = {
761
+ const toolkit = defineToolkit({
726
762
  analyzeData: {
727
763
  type: "backend",
728
764
  render: ({ result, status }) => {
@@ -757,7 +793,7 @@ const toolkit = {
757
793
  );
758
794
  },
759
795
  },
760
- } satisfies Toolkit;
796
+ });
761
797
  ```
762
798
 
763
799
  ### Custom Tool Fallback
@@ -802,7 +838,7 @@ type ToolCallMessagePartProps<TArgs, TResult> = {
802
838
  When a tool calls `human()` during execution, the payload becomes available in the render function as `interrupt.payload`:
803
839
 
804
840
  ```tsx
805
- const toolkit = {
841
+ const toolkit = defineToolkit({
806
842
  confirmAction: {
807
843
  type: "backend",
808
844
  render: ({ args, result, interrupt, resume }) => {
@@ -825,7 +861,7 @@ const toolkit = {
825
861
  return <div>Processing...</div>;
826
862
  },
827
863
  },
828
- } satisfies Toolkit;
864
+ });
829
865
  ```
830
866
 
831
867
  Learn more about tool human input in the [Tools Guide](/docs/tools/defining-tools#human-tools).
@@ -882,7 +918,7 @@ Use `useInlineRender` to prevent unnecessary re-renders:
882
918
  ```tsx title="heavy-computation-toolkit.tsx"
883
919
  "use client";
884
920
 
885
- import { type Toolkit, useInlineRender } from "@assistant-ui/react";
921
+ import { defineToolkit, useInlineRender } from "@assistant-ui/react";
886
922
  import { useMemo } from "react";
887
923
 
888
924
  export function useHeavyComputationToolkit() {
@@ -892,12 +928,12 @@ export function useHeavyComputationToolkit() {
892
928
 
893
929
  return useMemo(
894
930
  () =>
895
- ({
931
+ defineToolkit({
896
932
  heavyComputation: {
897
933
  type: "backend",
898
934
  render: renderHeavyComputation,
899
935
  },
900
- }) satisfies Toolkit,
936
+ }),
901
937
  [renderHeavyComputation],
902
938
  );
903
939
  }
@@ -17,12 +17,12 @@ Both flow through one connection lifecycle, one persisted state surface, and one
17
17
  ```
18
18
  useAui({ mcp: McpManagerResource({ connectors }) })
19
19
  │
20
- ├─ Tap resource — connection lifecycle, server lookup, OAuth/bearer auth
20
+ ├─ Resource — connection lifecycle, server lookup, OAuth/bearer auth
21
21
  ├─ Auto-mounts the modelContext scope when no chat runtime provides one
22
22
  └─ Registers connected tools as frontend tools — your chat sees them automatically
23
23
  ```
24
24
 
25
- The manager is a single tap resource. Mount it with `useAui` like any other scope. OAuth (PKCE + RFC 7591 dynamic client registration), bearer, and "no auth" are first-class. Token refresh runs inside the MCP SDK on 401; this package mediates persistence and the redirect step.
25
+ The manager is a single resource. Mount it with `useAui` like any other scope. OAuth (PKCE + RFC 7591 dynamic client registration), bearer, and "no auth" are first-class. Token refresh runs inside the MCP SDK on 401; this package mediates persistence and the redirect step.
26
26
 
27
27
  ## Setup
28
28
 
@@ -221,7 +221,7 @@ Tool names are prefixed `serverId__toolName` to avoid collisions across connecte
221
221
  If no chat runtime is mounted, `McpManagerResource` brings its own minimal `modelContext` along. Tools are still callable directly:
222
222
 
223
223
  ```ts
224
- // In an event handler — never in render. See the tap conventions.
224
+ // In an event handler, never in render.
225
225
  const aui = useAui();
226
226
  const out = await aui.mcp().server({ id: "linear" }).callTool("search", { q });
227
227
  ```
@@ -293,7 +293,7 @@ const connectionState = useAuiState((s) => s.mcpServer.connectionState);
293
293
  // ^ requires McpServerByIdProvider
294
294
  ```
295
295
 
296
- Imperative methods — `useAui` + resolve in a callback (never during render — see the [tap skill](https://github.com/assistant-ui/assistant-ui/blob/main/.claude/skills/tap/SKILL.md) for why):
296
+ Imperative methods: `useAui` + resolve in a callback (never during render):
297
297
 
298
298
  ```ts
299
299
  const aui = useAui();
@@ -0,0 +1,133 @@
1
+ ---
2
+ title: Dot Matrix
3
+ description: Tiny 5x5 dot-matrix indicator with 20 state-specific blink patterns.
4
+ platforms: ["react"]
5
+ ---
6
+
7
+ import { PreviewCode } from "@/components/docs/preview-code.server";
8
+ import {
9
+ DotMatrixSample,
10
+ DotMatrixLifecycleSample,
11
+ DotMatrixInlineSample,
12
+ DotMatrixSizesSample,
13
+ } from "@/components/docs/samples/dot-matrix";
14
+
15
+ <Callout>
16
+ This is a **standalone component** that does not depend on the assistant-ui runtime. Use it anywhere in your application.
17
+ </Callout>
18
+
19
+ <DotMatrixSample />
20
+
21
+ ## Installation
22
+
23
+ <InstallCommand shadcn={["dot-matrix"]} />
24
+
25
+ This adds a `/components/assistant-ui/dot-matrix.tsx` file to your project, which you can adjust as needed. The component has no dependencies beyond React.
26
+
27
+ ## Usage
28
+
29
+ ```tsx
30
+ import { DotMatrix } from "@/components/assistant-ui/dot-matrix";
31
+
32
+ export function RunIndicator({ isRunning }: { isRunning: boolean }) {
33
+ return <DotMatrix state={isRunning ? "loading" : "success"} />;
34
+ }
35
+ ```
36
+
37
+ Dots inherit the surrounding text color, so the matrix renders dark dots on light backgrounds and light dots on dark backgrounds without configuration. Every state is a combination of a dot pattern, a motion, and a color, and switching states cross-fades each dot into its new pattern.
38
+
39
+ ## States
40
+
41
+ | State | Pattern |
42
+ |-------|---------|
43
+ | `idle` | Dim static grid |
44
+ | `loading` | Randomized twinkle (default) |
45
+ | `thinking` | Diagonal wave |
46
+ | `streaming` | Falling rain, per-column streaks |
47
+ | `searching` | Horizontal sweep |
48
+ | `syncing` | Rotating sweep around the center |
49
+ | `connecting` | Ripple expanding from the center |
50
+ | `waiting` | Ellipsis dots blinking in sequence |
51
+ | `uploading` | Wave rising upward |
52
+ | `downloading` | Wave falling downward |
53
+ | `listening` | Slow equalizer columns |
54
+ | `speaking` | Fast equalizer columns |
55
+ | `recording` | Red center dot breathing |
56
+ | `success` | Green check glyph, static |
57
+ | `error` | Red cross glyph, blinking |
58
+ | `warning` | Amber exclamation glyph, slow blink |
59
+ | `info` | Blue info glyph, static |
60
+ | `paused` | Pause bars glyph, static |
61
+ | `stopped` | Square glyph, static |
62
+ | `offline` | Very dim static grid |
63
+
64
+ The component exports `dotMatrixStates` (the ordered list above) and the `DotMatrixState` union type, so UIs can enumerate or map states without duplicating the list. New states are added by extending the `STATES` record in the component source with a glyph and a per-dot blink function.
65
+
66
+ ## Examples
67
+
68
+ ### State Lifecycle
69
+
70
+ Drive the `state` prop from your run status; the matrix morphs between patterns instead of swapping components.
71
+
72
+ <PreviewCode file="components/docs/samples/dot-matrix" name="DotMatrixLifecycleSample">
73
+ <DotMatrixLifecycleSample />
74
+ </PreviewCode>
75
+
76
+ ### Inline With Text
77
+
78
+ At the default `size-4` the matrix aligns with text like an icon, and the dots adapt to inverted surfaces through `currentColor`.
79
+
80
+ <PreviewCode file="components/docs/samples/dot-matrix" name="DotMatrixInlineSample">
81
+ <DotMatrixInlineSample />
82
+ </PreviewCode>
83
+
84
+ ### Sizes
85
+
86
+ The matrix is an SVG, so any size utility scales it crisply.
87
+
88
+ <DotMatrixSizesSample />
89
+
90
+ ## How It Works
91
+
92
+ The grid is a 5x5 SVG of `currentColor` circles. Blinking is a single CSS keyframe animation whose high/low opacity bounds come from registered per-dot CSS variables; the animation runs in every state (static states collapse the bounds) and the bounds carry a transition, which is what makes state changes cross-fade per dot. The randomized loading rhythm uses deterministic per-dot delays and durations, so server and client render identical markup and no JavaScript runs after render. With `prefers-reduced-motion`, the dots hold their resting opacity instead of blinking.
93
+
94
+ The root is a `role="status"` live region whose text content is the state name (or the `label` prop), so screen readers announce state changes; the SVG itself is `aria-hidden`.
95
+
96
+ ## API Reference
97
+
98
+ ### DotMatrix
99
+
100
+ <ParametersTable
101
+ type="DotMatrixProps"
102
+ parameters={[
103
+ {
104
+ name: "state",
105
+ type: "DotMatrixState",
106
+ default: '"loading"',
107
+ description:
108
+ "One of the 20 built-in states listed above, controlling pattern, motion, and color.",
109
+ },
110
+ {
111
+ name: "label",
112
+ type: "string",
113
+ description:
114
+ "Accessible label announced by screen readers. Defaults to the state name.",
115
+ },
116
+ {
117
+ name: "className",
118
+ type: "string",
119
+ description:
120
+ "Additional CSS classes. Use size utilities to scale and text color utilities to recolor.",
121
+ },
122
+ ]}
123
+ />
124
+
125
+ ### Styling
126
+
127
+ Color follows `currentColor`, so `className="text-blue-500"` recolors the whole matrix; the outcome states (`success`, `error`, `warning`, `info`, `recording`, and the muted static states) set their own color which a `className` can override. Dots are targetable via `[data-slot="dot-matrix"]` and `[data-slot="dot-matrix-dot"]`, and the current state is exposed as `data-state` on the root.
128
+
129
+ ## Related Components
130
+
131
+ - [Number Roll](/docs/ui/number-roll) - Animated rolling number
132
+ - [Badge](/docs/ui/badge) - Small status and metadata labels
133
+ - [Voice](/docs/ui/voice) - Voice activity visualization
@@ -50,34 +50,41 @@ export const MarkdownText = memo(MarkdownTextImpl);
50
50
 
51
51
  ## Configuration
52
52
 
53
- Configure mermaid options in `mermaid-diagram.tsx`:
53
+ Configure rendering options in `mermaid-diagram.tsx`:
54
54
 
55
55
  ```tsx title="/components/assistant-ui/mermaid-diagram.tsx"
56
- mermaid.initialize({ theme: "default" });
56
+ renderMermaidSVG(code, {
57
+ bg: "var(--background)",
58
+ fg: "var(--foreground)",
59
+ muted: "var(--muted-foreground)",
60
+ border: "var(--border)",
61
+ accent: "var(--foreground)",
62
+ transparent: true,
63
+ });
57
64
  ```
58
65
 
66
+ The palette follows your theme's background, foreground, and shadcn color tokens, so diagrams match light and dark mode automatically.
67
+
59
68
  ## Streaming Performance
60
69
 
61
70
  The `MermaidDiagram` component is optimized for streaming scenarios:
62
71
 
63
- - **Smart completion detection**: Only renders when the specific code block is complete
64
- - **Zero failed renders**: Avoids parsing incomplete diagram code during streaming
72
+ - **Skeleton while streaming**: Shows a placeholder skeleton until the response finishes streaming, then renders the diagram synchronously
73
+ - **Raw source fallback**: Invalid or unsupported diagrams fall back to displaying the raw source
65
74
 
66
75
 
67
76
  ## Supported Diagram Types
68
77
 
69
- Mermaid supports various diagram types including:
78
+ The component renders these diagram types:
70
79
 
71
80
  - Flowcharts and decision trees
72
81
  - Sequence diagrams
73
- - Gantt charts
74
82
  - Class diagrams
75
83
  - State diagrams
76
- - Git graphs
77
- - User journey maps
78
84
  - Entity relationship diagrams
85
+ - XY charts (bar, line, combined)
79
86
 
80
- See the [Mermaid documentation](https://mermaid.js.org/) for complete syntax reference.
87
+ Other mermaid diagram types fall back to displaying the raw source. See the [Mermaid documentation](https://mermaid.js.org/) for syntax reference.
81
88
 
82
89
  ## Related Components
83
90