@tailor-platform/app-shell 1.19.0 → 1.20.0

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 (46) hide show
  1. package/dist/app-shell-core.css +2 -2
  2. package/dist/app-shell.d.ts +807 -130
  3. package/dist/app-shell.js +12419 -10930
  4. package/dist/{appshell-DQTz-QwK.js → appshell-B4QkQvXF.js} +377 -360
  5. package/dist/fonts/inter.css +7 -7
  6. package/dist/fonts/noto-sans-jp.css +116 -116
  7. package/dist/testing.d.ts +119 -89
  8. package/dist/testing.js +1 -1
  9. package/dist/vite-plugin.d.ts +119 -89
  10. package/package.json +10 -8
  11. package/skills/app-shell-patterns/SKILL.md +4 -3
  12. package/skills/app-shell-patterns/references/api/create-ai-gateway-client.md +32 -2
  13. package/skills/app-shell-patterns/references/api/define-module.md +5 -5
  14. package/skills/app-shell-patterns/references/api/router/use-params.md +2 -2
  15. package/skills/app-shell-patterns/references/api/use-ai-chat.md +46 -8
  16. package/skills/app-shell-patterns/references/api/use-app-shell-config.md +4 -4
  17. package/skills/app-shell-patterns/references/api/use-app-shell-data.md +5 -5
  18. package/skills/app-shell-patterns/references/api/use-app-shell.md +2 -2
  19. package/skills/app-shell-patterns/references/api/use-auth.md +3 -3
  20. package/skills/app-shell-patterns/references/api/use-route-error.md +12 -12
  21. package/skills/app-shell-patterns/references/components/action-panel.md +4 -2
  22. package/skills/app-shell-patterns/references/components/activity-card.md +3 -3
  23. package/skills/app-shell-patterns/references/components/ai-chat.md +37 -3
  24. package/skills/app-shell-patterns/references/components/app-shell.md +6 -5
  25. package/skills/app-shell-patterns/references/components/card.md +2 -2
  26. package/skills/app-shell-patterns/references/components/data-table.md +87 -31
  27. package/skills/app-shell-patterns/references/components/date-picker.md +2 -2
  28. package/skills/app-shell-patterns/references/components/default-sidebar.md +2 -2
  29. package/skills/app-shell-patterns/references/components/dialog.md +8 -0
  30. package/skills/app-shell-patterns/references/components/filter-rail.md +10 -3
  31. package/skills/app-shell-patterns/references/components/form.md +5 -5
  32. package/skills/app-shell-patterns/references/components/global-header-layout.md +31 -8
  33. package/skills/app-shell-patterns/references/components/layout.md +24 -17
  34. package/skills/app-shell-patterns/references/components/select.md +8 -0
  35. package/skills/app-shell-patterns/references/components/sidebar-group.md +9 -7
  36. package/skills/app-shell-patterns/references/components/sidebar-layout.md +74 -11
  37. package/skills/app-shell-patterns/references/components/sidebar-section.md +8 -8
  38. package/skills/app-shell-patterns/references/components/tabs.md +32 -2
  39. package/skills/app-shell-patterns/references/components/tree.md +342 -0
  40. package/skills/app-shell-patterns/references/components/with-guard.md +5 -5
  41. package/skills/app-shell-patterns/references/concepts/authentication.md +1 -1
  42. package/skills/app-shell-patterns/references/concepts/routing-navigation.md +3 -3
  43. package/skills/app-shell-patterns/references/concepts/styling-theming.md +13 -13
  44. package/skills/app-shell-patterns/references/migrations.md +20 -0
  45. package/skills/app-shell-patterns/references/pages/document-detail.md +8 -12
  46. package/skills/app-shell-patterns/references/patterns/interaction-multi-select.md +1 -1
@@ -182,7 +182,7 @@ function ProductEdit() {
182
182
 
183
183
  return (
184
184
  <form>
185
- <h1>Edit Product {id}</h1>
185
+ <Text.h1>Edit Product {id}</Text.h1>
186
186
  {/* form fields */}
187
187
  </form>
188
188
  );
@@ -203,7 +203,7 @@ function DeleteConfirmation() {
203
203
 
204
204
  return (
205
205
  <div>
206
- <p>Delete product {id}?</p>
206
+ <Text.p>Delete product {id}?</Text.p>
207
207
  <button onClick={handleDelete}>Confirm</button>
208
208
  </div>
209
209
  );
@@ -1,19 +1,24 @@
1
1
  ---
2
2
  title: useAIChat
3
- description: Simple text-only chat hook for AI Gateway
3
+ description: AI Gateway chat hook with optional local tools
4
4
  ---
5
5
 
6
6
  <!-- GENERATED by docs-kit from docs-src/hooks/use-ai-chat.docs.outline.md — do not edit by hand. -->
7
7
 
8
8
  # useAIChat
9
9
 
10
- React hook for simple text-only chat on top of `createAIGatewayClient`.
10
+ React hook for AI Gateway chat on top of `createAIGatewayClient`, with optional local tool support.
11
11
 
12
12
  ## Signature
13
13
 
14
14
  ```typescript
15
- const useAIChat: (config: { client: AIGatewayClient; model: string }) => {
15
+ const useAIChat: (config: {
16
+ client: AIGatewayClient;
17
+ model: string;
18
+ tools?: Record<string, AILocalTool>;
19
+ }) => {
16
20
  messages: AIChatMessage[];
21
+ toolCalls: { id: string; name: string }[];
17
22
  status: "ready" | "submitted" | "streaming" | "error";
18
23
  error?: Error;
19
24
  sendMessage: (message: string) => Promise<boolean>;
@@ -33,10 +38,17 @@ interface AIChatMessage {
33
38
  }
34
39
  ```
35
40
 
41
+ ### `toolCalls`
42
+
43
+ - **Type:** `{ id: string; name: string }[]`
44
+ - **Description:** Tool calls requested by the model in the active flow, including earlier tool rounds of the current request. This transient list is cleared when the response finishes, is stopped, or fails; it is never added to `messages` or conversation history.
45
+
46
+ Calls become available before local tool execution. They record requested tool names, not successful execution. Arguments and results remain internal.
47
+
36
48
  ### `status`
37
49
 
38
50
  - **Type:** `"ready" | "submitted" | "streaming" | "error"`
39
- - **Description:** Current request state
51
+ - **Description:** Current request state. `submitted` covers waiting for the first text, local tool execution, and waiting for the model's next reply after a tool result. `streaming` begins when text arrives. `AIChat.Conversation` automatically shows a waiting indicator while `submitted`.
40
52
 
41
53
  ### `error`
42
54
 
@@ -54,10 +66,20 @@ interface AIChatMessage {
54
66
  - **Type:** `() => void`
55
67
  - **Description:** Aborts the current request if one is in progress
56
68
 
69
+ ### `tools`
70
+
71
+ Register local tools under a single object using `defineAIChatTool(...)`. Their schemas must implement both [Standard Schema](https://standardschema.dev/) validation and Standard JSON Schema generation (for example, Zod 4). Provider-native tools are not supported.
72
+
57
73
  ## Usage
58
74
 
59
75
  ```tsx
60
- import { createAuthClient, createAIGatewayClient, useAIChat } from "@tailor-platform/app-shell";
76
+ import {
77
+ createAuthClient,
78
+ createAIGatewayClient,
79
+ defineAIChatTool,
80
+ useAIChat,
81
+ } from "@tailor-platform/app-shell";
82
+ import { z } from "zod/v4";
61
83
 
62
84
  const authClient = createAuthClient({
63
85
  clientId: "your-client-id",
@@ -69,10 +91,23 @@ const aiClient = createAIGatewayClient({
69
91
  authClient,
70
92
  });
71
93
 
94
+ const lookupCustomer = defineAIChatTool({
95
+ description: "Look up a customer in the current workspace",
96
+ schema: z.object({
97
+ customerId: z.string(),
98
+ }),
99
+ async execute({ customerId }) {
100
+ return { customerId, name: "Acme Corp" };
101
+ },
102
+ });
103
+
72
104
  export function ChatScreen() {
73
- const { messages, sendMessage, status, stop, error } = useAIChat({
105
+ const { messages, toolCalls, sendMessage, status, stop, error } = useAIChat({
74
106
  client: aiClient,
75
107
  model: "gpt-5-mini",
108
+ tools: {
109
+ lookupCustomer,
110
+ },
76
111
  });
77
112
 
78
113
  return (
@@ -82,6 +117,9 @@ export function ChatScreen() {
82
117
  {message.role}: {message.content}
83
118
  </div>
84
119
  ))}
120
+ {toolCalls.map((call) => (
121
+ <div key={call.id}>Tool call: {call.name}</div>
122
+ ))}
85
123
 
86
124
  <button
87
125
  onClick={() => void sendMessage("Hello")}
@@ -101,9 +139,9 @@ export function ChatScreen() {
101
139
  ## Notes
102
140
 
103
141
  - AppShell chooses the appropriate AI Gateway transport automatically
104
- - The hook is intentionally text-only
142
+ - Public messages stay user/assistant text-first; tool calls and results never become conversation messages
105
143
  - System prompts and custom history shaping should use the low-level client directly
106
- - `stop()` keeps any already-streamed assistant text and ignores late chunks from the stopped request
144
+ - `stop()` keeps already-streamed assistant text, clears the active `toolCalls`, and ignores late events from the stopped request
107
145
 
108
146
  ## Related
109
147
 
@@ -56,15 +56,15 @@ const useAppShellConfig: () => {
56
56
  ### Display App Info
57
57
 
58
58
  ```typescript
59
- import { useAppShellConfig } from "@tailor-platform/app-shell";
59
+ import { Text, useAppShellConfig } from "@tailor-platform/app-shell";
60
60
 
61
61
  function AppInfo() {
62
62
  const { title, configurations } = useAppShellConfig();
63
63
 
64
64
  return (
65
65
  <div>
66
- <h2>{title}</h2>
67
- <p>Base: {configurations.basePath}</p>
66
+ <Text.h2>{title}</Text.h2>
67
+ <Text.p>Base: {configurations.basePath}</Text.p>
68
68
  </div>
69
69
  );
70
70
  }
@@ -96,7 +96,7 @@ function SettingsMenu() {
96
96
 
97
97
  return (
98
98
  <div>
99
- <h3>Settings</h3>
99
+ <Text.h3>Settings</Text.h3>
100
100
  {configurations.settingsResources.map((resource) => (
101
101
  <button key={resource.path}>{resource.path}</button>
102
102
  ))}
@@ -28,15 +28,15 @@ const useAppShellData: () => {
28
28
  ### Basic Access
29
29
 
30
30
  ```typescript
31
- import { useAppShellData } from "@tailor-platform/app-shell";
31
+ import { Text, useAppShellData } from "@tailor-platform/app-shell";
32
32
 
33
33
  function UserProfile() {
34
34
  const { contextData } = useAppShellData();
35
35
 
36
36
  return (
37
37
  <div>
38
- <p>Welcome, {contextData.currentUser?.name}</p>
39
- <p>Role: {contextData.currentUser?.role}</p>
38
+ <Text.p>Welcome, {contextData.currentUser?.name}</Text.p>
39
+ <Text.p>Role: {contextData.currentUser?.role}</Text.p>
40
40
  </div>
41
41
  );
42
42
  }
@@ -54,8 +54,8 @@ function UserInfo() {
54
54
 
55
55
  return (
56
56
  <div>
57
- <h2>{contextData.currentUser.name}</h2>
58
- <p>{contextData.currentUser.email}</p>
57
+ <Text.h2>{contextData.currentUser.name}</Text.h2>
58
+ <Text.p>{contextData.currentUser.email}</Text.p>
59
59
  </div>
60
60
  );
61
61
  }
@@ -120,8 +120,8 @@ function UserInfo() {
120
120
 
121
121
  return (
122
122
  <div>
123
- <h2>{contextData.currentUser.name}</h2>
124
- <p>{contextData.currentUser.email}</p>
123
+ <Text.h2>{contextData.currentUser.name}</Text.h2>
124
+ <Text.p>{contextData.currentUser.email}</Text.p>
125
125
  </div>
126
126
  );
127
127
  }
@@ -59,7 +59,7 @@ const useAuth: () => {
59
59
  ### Basic Authentication Flow
60
60
 
61
61
  ```typescript
62
- import { useAuth } from "@tailor-platform/app-shell";
62
+ import { Text, useAuth } from "@tailor-platform/app-shell";
63
63
 
64
64
  function MyComponent() {
65
65
  const { isAuthenticated, isReady, login, logout } = useAuth();
@@ -74,7 +74,7 @@ function MyComponent() {
74
74
 
75
75
  return (
76
76
  <div>
77
- <p>You are logged in!</p>
77
+ <Text.p>You are logged in!</Text.p>
78
78
  <button onClick={logout}>Log Out</button>
79
79
  </div>
80
80
  );
@@ -108,7 +108,7 @@ function AuthStatus() {
108
108
  if (error) {
109
109
  return (
110
110
  <div>
111
- <p>Authentication failed: {error}</p>
111
+ <Text.p>Authentication failed: {error}</Text.p>
112
112
  <button onClick={login}>Retry</button>
113
113
  </div>
114
114
  );
@@ -26,7 +26,7 @@ const useRouteError: () => unknown;
26
26
  ### Basic Error Boundary
27
27
 
28
28
  ```typescript
29
- import { useRouteError } from "@tailor-platform/app-shell";
29
+ import { Text, useRouteError } from "@tailor-platform/app-shell";
30
30
 
31
31
  function ErrorBoundary() {
32
32
  const error = useRouteError();
@@ -37,8 +37,8 @@ function ErrorBoundary() {
37
37
 
38
38
  return (
39
39
  <div>
40
- <h1>Something went wrong</h1>
41
- <p>{message}</p>
40
+ <Text.h1>Something went wrong</Text.h1>
41
+ <Text.p>{message}</Text.p>
42
42
  <button onClick={() => window.location.reload()}>
43
43
  Try Again
44
44
  </button>
@@ -79,7 +79,7 @@ const productsModule = defineModule({
79
79
  ### Advanced Error Handling
80
80
 
81
81
  ```typescript
82
- import { isRouteErrorResponse, useRouteError } from "@tailor-platform/app-shell";
82
+ import { isRouteErrorResponse, Text, useRouteError } from "@tailor-platform/app-shell";
83
83
 
84
84
  function ErrorBoundary() {
85
85
  const error = useRouteError();
@@ -88,8 +88,8 @@ function ErrorBoundary() {
88
88
  if (isRouteErrorResponse(error)) {
89
89
  return (
90
90
  <div>
91
- <h1>{error.status} {error.statusText}</h1>
92
- <p>{error.data}</p>
91
+ <Text.h1>{error.status} {error.statusText}</Text.h1>
92
+ <Text.p>{error.data}</Text.p>
93
93
  </div>
94
94
  );
95
95
  }
@@ -98,8 +98,8 @@ function ErrorBoundary() {
98
98
  if (error instanceof Error) {
99
99
  return (
100
100
  <div>
101
- <h1>Error</h1>
102
- <p>{error.message}</p>
101
+ <Text.h1>Error</Text.h1>
102
+ <Text.p>{error.message}</Text.p>
103
103
  <pre>{error.stack}</pre>
104
104
  </div>
105
105
  );
@@ -108,8 +108,8 @@ function ErrorBoundary() {
108
108
  // Handle unknown errors
109
109
  return (
110
110
  <div>
111
- <h1>Unknown Error</h1>
112
- <p>Something went wrong</p>
111
+ <Text.h1>Unknown Error</Text.h1>
112
+ <Text.p>Something went wrong</Text.p>
113
113
  </div>
114
114
  );
115
115
  }
@@ -129,8 +129,8 @@ function ErrorBoundary() {
129
129
 
130
130
  return (
131
131
  <div>
132
- <h1>Error</h1>
133
- <p>We've been notified and will fix this soon.</p>
132
+ <Text.h1>Error</Text.h1>
133
+ <Text.p>We've been notified and will fix this soon.</Text.p>
134
134
  </div>
135
135
  );
136
136
  }
@@ -94,8 +94,10 @@ function CustomEmptyContent() {
94
94
  actions={[]}
95
95
  emptyContent={
96
96
  <div>
97
- <p>利用可能な操作はありません</p>
98
- <p>ステータスが変わると、操作が表示されます。</p>
97
+ <Text.p className="text-muted-foreground">利用可能な操作はありません</Text.p>
98
+ <Text.p className="text-muted-foreground">
99
+ ステータスが変わると、操作が表示されます。
100
+ </Text.p>
99
101
  </div>
100
102
  }
101
103
  />
@@ -105,7 +105,7 @@ import { ActivityCard, type ActivityCardBaseItem } from "@tailor-platform/app-sh
105
105
  ### Example
106
106
 
107
107
  ```tsx
108
- import { ActivityCard, type ActivityCardBaseItem } from "@tailor-platform/app-shell";
108
+ import { ActivityCard, Text, type ActivityCardBaseItem } from "@tailor-platform/app-shell";
109
109
 
110
110
  interface MyItem extends ActivityCardBaseItem {
111
111
  kind: "approval" | "update";
@@ -123,11 +123,11 @@ const items: MyItem[] = [
123
123
  {(item) =>
124
124
  item.kind === "approval" ? (
125
125
  <ActivityCard.Item indicator={<ApprovedIcon />}>
126
- <p>{item.label}</p>
126
+ <Text.p>{item.label}</Text.p>
127
127
  </ActivityCard.Item>
128
128
  ) : (
129
129
  <ActivityCard.Item>
130
- <p>{item.message}</p>
130
+ <Text.p>{item.message}</Text.p>
131
131
  </ActivityCard.Item>
132
132
  )
133
133
  }
@@ -84,6 +84,17 @@ Other props spread onto the root `<div>`.
84
84
 
85
85
  Other props spread onto the region's outer `<div>`.
86
86
 
87
+ While the root's `status` is `"submitted"`, the conversation automatically appends a [`Spinner`](./spinner.md) and localized “Thinking…” status at the end. This covers the initial reply wait, tool execution, and the next reply wait after a tool result. The indicator disappears when text starts streaming, or when the request finishes, fails, or is stopped. It participates in the conversation's normal auto-scroll behavior; no separate loader state is needed.
88
+
89
+ ### `AIChat.ToolCall`
90
+
91
+ A compact label for one model-requested tool call. Each label occupies its own row, so multiple calls stack vertically. It does not imply execution success, render tool arguments/results, or manage history.
92
+
93
+ | Prop | Type | Default | Description |
94
+ | ----------- | ------------------------------ | -------- | ------------------------------------------------ |
95
+ | `call` | `{ id: string; name: string }` | required | A `toolCalls` element returned by `useAIChat()`. |
96
+ | `className` | `string` | - | Merged onto the outer row, not the badge. |
97
+
87
98
  ### `AIChat.Composer`
88
99
 
89
100
  | Prop | Type | Default | Description |
@@ -112,17 +123,18 @@ Most props stay inside their region. These `AIChat.Composer` props land on **ano
112
123
 
113
124
  `onValueChange` is wrapped rather than forwarded — it is called from the `Textarea`'s `onChange`, and again with `""` after a submit. `defaultValue` seeds the composer's own state and is never forwarded. Nothing on `AIChat`, `AIChat.Header`, or `AIChat.Conversation` reaches another AppShell component.
114
125
 
115
- Three attached parts wrap an AppShell component. They expose only the props the part's job needs rather than inheriting the wrapped component's surface, so its visual treatment is fixed and not yours to change:
126
+ Four attached parts wrap an AppShell component. They expose only the props the part's job needs rather than inheriting the wrapped component's surface, so its visual treatment is fixed and not yours to change:
116
127
 
117
128
  | Part | Wraps | Accepts | Fixed |
118
129
  | ----------------------------------- | ---------------------------------------------------------- | ------------------------------------------------------------- | ---------------------------------- |
119
130
  | `AIChat.Suggestion` | [`Button`](./button.md) | `suggestion`, `onSelect`, `className`, `disabled`, `children` | `variant="secondary"`, `size="sm"` |
120
131
  | `AIChat.Action` | [`Button`](./button.md) inside a [`Tooltip`](./tooltip.md) | `label`, `onClick`, `className`, `disabled`, `children` | `variant="ghost"`, `size="icon"` |
121
132
  | `AIChat.ChainOfThoughtSearchResult` | [`Badge`](./badge.md) | `className`, `children`, `variant` | — |
133
+ | `AIChat.ToolCall` | [`Badge`](./badge.md) | `call`, `className` | `variant="neutral"` |
122
134
 
123
135
  `variant` stays open on `ChainOfThoughtSearchResult` because conveying status is what a `Badge` is for. `AIChat.Action`'s `label` becomes both the accessible name and the tooltip text.
124
136
 
125
- One thing to know about `className` on these: it is merged with `cn()`, which is not configured for AppShell's internal prefix, so it cannot reliably override a base utility from the wrapped component. Add properties the component doesn't set, and reach for the wrapped component's own props or variants to change ones it does — see [Styling AppShell components](../concepts/styling-theming.md#styling-appshell-components).
137
+ `ToolCall` applies `className` to its outer row, not the inner badge. For `Suggestion`, `Action`, and `ChainOfThoughtSearchResult`, `className` is merged with `cn()`, which is not configured for AppShell's internal prefix, so it cannot reliably override a base utility from the wrapped component. Add properties the component doesn't set, and reach for the wrapped component's own props or variants to change ones it does — see [Styling AppShell components](../concepts/styling-theming.md#styling-appshell-components).
126
138
 
127
139
  ## Filling the page
128
140
 
@@ -261,6 +273,28 @@ Structured step timeline for agentic turns — the discrete plan being executed,
261
273
 
262
274
  `status` is `"complete" | "active" | "pending"`.
263
275
 
276
+ ### Tool calls during the active flow
277
+
278
+ `useAIChat()` returns a transient `toolCalls` list separately from `messages`. Render it with `AIChat.ToolCall` after the message history inside `AIChat.Conversation`:
279
+
280
+ ```tsx
281
+ {
282
+ toolCalls.length > 0 ? (
283
+ <AIChat.Message from="assistant">
284
+ {toolCalls.map((call) => (
285
+ <AIChat.ToolCall key={call.id} call={call} />
286
+ ))}
287
+ </AIChat.Message>
288
+ ) : null;
289
+ }
290
+ ```
291
+
292
+ Each call renders on its own row, in the order supplied. Labels are localized automatically.
293
+
294
+ The list clears when the response finishes, is stopped, or fails. It does not create tool messages or persist in the conversation log.
295
+
296
+ These names record model requests, not execution success. Tool arguments and results stay internal. Do not infer a `ToolHeader` success or running state from name-only metadata.
297
+
264
298
  ### Tool
265
299
 
266
300
  Collapsible tool-call card. Maps 1:1 to the AI SDK's tool-part lifecycle, so a streaming loop can update a call in place as parts arrive.
@@ -279,7 +313,7 @@ Collapsible tool-call card. Maps 1:1 to the AI SDK's tool-part lifecycle, so a s
279
313
 
280
314
  ### Sources
281
315
 
282
- Compact "Used N sources" citation trigger under a grounded answer.
316
+ Compact "Used N sources" citation trigger under a grounded answer. Supply source data from your application; `useAIChat()` does not return citation metadata.
283
317
 
284
318
  ```tsx
285
319
  <AIChat.Sources>
@@ -232,14 +232,14 @@ Access the configured timezone in components using [`useTimeZone`](../api/use-ti
232
232
  - **Description:** Global error boundary component applied to all routes
233
233
 
234
234
  ```tsx
235
- import { useRouteError } from "@tailor-platform/app-shell";
235
+ import { Text, useRouteError } from "@tailor-platform/app-shell";
236
236
 
237
237
  const GlobalErrorBoundary = () => {
238
238
  const error = useRouteError() as Error;
239
239
  return (
240
240
  <div className="p-8">
241
- <h1 className="text-xl font-bold mb-4">Something went wrong</h1>
242
- <p className="text-red-600">{error.message}</p>
241
+ <Text.h1 className="mb-4">Something went wrong</Text.h1>
242
+ <Text.p className="text-danger-text">{error.message}</Text.p>
243
243
  </div>
244
244
  );
245
245
  };
@@ -432,6 +432,7 @@ import {
432
432
  SidebarLayout,
433
433
  defineModule,
434
434
  defineResource,
435
+ Text,
435
436
  useRouteError,
436
437
  } from "@tailor-platform/app-shell";
437
438
  import { Building } from "lucide-react";
@@ -450,8 +451,8 @@ const ErrorBoundary = () => {
450
451
  const error = useRouteError() as Error;
451
452
  return (
452
453
  <div className="p-8">
453
- <h1 className="text-xl font-bold">Error</h1>
454
- <p>{error.message}</p>
454
+ <Text.h1>Error</Text.h1>
455
+ <Text.p>{error.message}</Text.p>
455
456
  </div>
456
457
  );
457
458
  };
@@ -25,7 +25,7 @@ function BasicUsage() {
25
25
  <Card.Root>
26
26
  <Card.Header title="Order Details" description="Summary of order #1234" />
27
27
  <Card.Content>
28
- <p>Content goes here</p>
28
+ <Text.p>Content goes here</Text.p>
29
29
  </Card.Content>
30
30
  </Card.Root>
31
31
  );
@@ -154,7 +154,7 @@ For a scrollable list, put the overflow on `Card.Content`. Rows supply their own
154
154
  ```tsx
155
155
  <Card.Root>
156
156
  <Card.Content>
157
- <p>No header needed for this card.</p>
157
+ <Text.p>No header needed for this card.</Text.p>
158
158
  </Card.Content>
159
159
  </Card.Root>
160
160
  ```