@streamoid/ui 0.6.17 → 0.6.18

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 (131) hide show
  1. package/README.md +35 -18
  2. package/dist/docs/AGENTS.md +321 -0
  3. package/dist/docs/CreditWarningBanner.md +305 -0
  4. package/dist/docs/InvoiceHistoryMobile.md +222 -0
  5. package/dist/docs/ScAccess.md +259 -0
  6. package/dist/docs/ScAppCard.md +244 -0
  7. package/dist/docs/ScAppCardForCopilot.md +230 -0
  8. package/dist/docs/ScAppCardV3.md +273 -0
  9. package/dist/docs/ScAppField.md +308 -0
  10. package/dist/docs/ScAppListingCard.md +271 -0
  11. package/dist/docs/ScAppSwitchPanel.md +286 -0
  12. package/dist/docs/ScAppcardLogos.md +226 -0
  13. package/dist/docs/ScArtifaxInvite.md +262 -0
  14. package/dist/docs/ScArtifaxSidebar.md +330 -0
  15. package/dist/docs/ScAskAgentButton.md +307 -0
  16. package/dist/docs/ScBadges.md +261 -0
  17. package/dist/docs/ScBeacon.md +244 -0
  18. package/dist/docs/ScBillingHistoryHeader.md +210 -0
  19. package/dist/docs/ScBillingHistoryTableList.md +243 -0
  20. package/dist/docs/ScBillingLogsTableHeader.md +212 -0
  21. package/dist/docs/ScBillingLogsTableList.md +251 -0
  22. package/dist/docs/ScBriefCard.md +255 -0
  23. package/dist/docs/ScButton.md +251 -0
  24. package/dist/docs/ScCalendar.md +268 -0
  25. package/dist/docs/ScCalendarDateComps.md +264 -0
  26. package/dist/docs/ScCatalogixInvite.md +345 -0
  27. package/dist/docs/ScCatalogixSidebar.md +337 -0
  28. package/dist/docs/ScCatalogixStoreHeader.md +246 -0
  29. package/dist/docs/ScCatalogixStoreTableList.md +316 -0
  30. package/dist/docs/ScCheckField.md +233 -0
  31. package/dist/docs/ScCheckbox.md +272 -0
  32. package/dist/docs/ScCounter.md +235 -0
  33. package/dist/docs/ScCreditsUsageCard.md +247 -0
  34. package/dist/docs/ScCreditsUsageCardMobile.md +224 -0
  35. package/dist/docs/ScDefaultCard.md +269 -0
  36. package/dist/docs/ScDp.md +245 -0
  37. package/dist/docs/ScDrawer.md +318 -0
  38. package/dist/docs/ScFieldButton.md +255 -0
  39. package/dist/docs/ScFileField.md +268 -0
  40. package/dist/docs/ScGoogleSignIn.md +250 -0
  41. package/dist/docs/ScGuide.md +278 -0
  42. package/dist/docs/ScHDivider.md +213 -0
  43. package/dist/docs/ScHeader.md +222 -0
  44. package/dist/docs/ScImageField.md +253 -0
  45. package/dist/docs/ScInChatList.md +277 -0
  46. package/dist/docs/ScInChatMessage.md +205 -0
  47. package/dist/docs/ScInfoPopup.md +248 -0
  48. package/dist/docs/ScIntialProfileCover.md +233 -0
  49. package/dist/docs/ScInvoiceHistoryMobile.md +187 -0
  50. package/dist/docs/ScLogoUnit.md +232 -0
  51. package/dist/docs/ScMappingCard.md +241 -0
  52. package/dist/docs/ScMediaApproval.md +301 -0
  53. package/dist/docs/ScMediaSelect.md +310 -0
  54. package/dist/docs/ScMenuOptions.md +308 -0
  55. package/dist/docs/ScMobileBottomAction.md +252 -0
  56. package/dist/docs/ScMobileTopNav.md +279 -0
  57. package/dist/docs/ScModal.md +291 -0
  58. package/dist/docs/ScOnlyField.md +302 -0
  59. package/dist/docs/ScOnlyIcon.md +213 -0
  60. package/dist/docs/ScPagination.md +284 -0
  61. package/dist/docs/ScPairtext.md +287 -0
  62. package/dist/docs/ScPendingAction.md +238 -0
  63. package/dist/docs/ScPhtogenixInvite.md +275 -0
  64. package/dist/docs/ScPlanCard.md +302 -0
  65. package/dist/docs/ScPlanComparison.md +264 -0
  66. package/dist/docs/ScPlanDetailsCard.md +246 -0
  67. package/dist/docs/ScPlanDetailsCardMobile.md +240 -0
  68. package/dist/docs/ScPopUpMenu.md +224 -0
  69. package/dist/docs/ScProfile.md +234 -0
  70. package/dist/docs/ScProfileImageUpdate.md +261 -0
  71. package/dist/docs/ScProfileOptions.md +245 -0
  72. package/dist/docs/ScProfilePopup.md +396 -0
  73. package/dist/docs/ScProfileSettingsComp.md +250 -0
  74. package/dist/docs/ScProfileV2Mobile.md +216 -0
  75. package/dist/docs/ScProgressBar.md +267 -0
  76. package/dist/docs/ScQuickPrompt.md +277 -0
  77. package/dist/docs/ScRadio.md +228 -0
  78. package/dist/docs/ScReferralCardMobile.md +226 -0
  79. package/dist/docs/ScReferralTableHeader.md +260 -0
  80. package/dist/docs/ScReferralTableList.md +293 -0
  81. package/dist/docs/ScRole.md +226 -0
  82. package/dist/docs/ScRoleMobile.md +199 -0
  83. package/dist/docs/ScSelect.md +270 -0
  84. package/dist/docs/ScSelection.md +256 -0
  85. package/dist/docs/ScSelectionList.md +272 -0
  86. package/dist/docs/ScSelectionPill.md +240 -0
  87. package/dist/docs/ScSelectionPillGroup.md +302 -0
  88. package/dist/docs/ScSettingsNav.md +212 -0
  89. package/dist/docs/ScSettingsTabComp.md +260 -0
  90. package/dist/docs/ScSideBarLogoUnit.md +340 -0
  91. package/dist/docs/ScSidebar.md +243 -0
  92. package/dist/docs/ScSidebarIcons.md +232 -0
  93. package/dist/docs/ScSidebarMenu.md +283 -0
  94. package/dist/docs/ScSidebarProfile.md +231 -0
  95. package/dist/docs/ScSidebarSwitchMenu.md +258 -0
  96. package/dist/docs/ScSlider.md +194 -0
  97. package/dist/docs/ScStoreCard.md +252 -0
  98. package/dist/docs/ScStrLogo.md +253 -0
  99. package/dist/docs/ScStreamoidWordmark.md +302 -0
  100. package/dist/docs/ScSubAgent.md +226 -0
  101. package/dist/docs/ScTabComp.md +308 -0
  102. package/dist/docs/ScTabField.md +258 -0
  103. package/dist/docs/ScTabSwitcher.md +307 -0
  104. package/dist/docs/ScTableHeader.md +261 -0
  105. package/dist/docs/ScTableList.md +301 -0
  106. package/dist/docs/ScTableListMobile.md +282 -0
  107. package/dist/docs/ScTabs.md +268 -0
  108. package/dist/docs/ScTaxonomyPill.md +263 -0
  109. package/dist/docs/ScTextArea.md +259 -0
  110. package/dist/docs/ScTextField.md +324 -0
  111. package/dist/docs/ScThinkingStepIcon.md +249 -0
  112. package/dist/docs/ScTodoList.md +288 -0
  113. package/dist/docs/ScToggleSwitch.md +229 -0
  114. package/dist/docs/ScUsageHistoryMobile.md +194 -0
  115. package/dist/docs/ScVDivider.md +215 -0
  116. package/dist/docs/ScValueMappingL1.md +256 -0
  117. package/dist/docs/ScVersion.md +251 -0
  118. package/dist/docs/ScWorkspace.md +233 -0
  119. package/dist/docs/ScWorkspaceCard.md +234 -0
  120. package/dist/docs/ScWorkspaceSettingsMobile.md +265 -0
  121. package/dist/docs/ScWorkspaceSwitchCard.md +314 -0
  122. package/dist/docs/ScWorkspaceSwitchMobile.md +241 -0
  123. package/dist/docs/ScWorkspaceSwitchMobileV2.md +278 -0
  124. package/dist/docs/StreamoidSidebar.md +403 -0
  125. package/dist/docs/StreamoidWorkspaceSwitcher.md +307 -0
  126. package/dist/docs/UsageHistoryMobile.md +235 -0
  127. package/dist/docs/components.json +4849 -0
  128. package/dist/index.css +36 -36
  129. package/dist/index.d.mts +10 -0
  130. package/dist/index.d.ts +10 -0
  131. package/package.json +3 -2
@@ -0,0 +1,277 @@
1
+ ---
2
+ component: ScInChatList
3
+ package: "@streamoid/ui"
4
+ category: chat-agent
5
+ status: stable
6
+ renders: div
7
+ tags: [chat, agent, thinking, reasoning, step, tool, transcript, progress, inchat]
8
+ related: [ScThinkingStepIcon, ScSubAgent, ScInChatMessage, ScTodoList]
9
+ do_not_confuse_with: [ScSubAgent, ScInChatMessage, ScTableList, ScMenuOptions]
10
+ used_by: [agent]
11
+ ---
12
+
13
+ # ScInChatList
14
+
15
+ **One reasoning step in the agent transcript — not a list.** A leading status glyph,
16
+ a single-line truncating title, an optional expandable description, and an optional
17
+ "Using <tool>…" pill. You render one per step and stack them yourself.
18
+
19
+ ## TL;DR for agents
20
+
21
+ - **Reach for it when:** you are rendering the agent's thinking/tool steps in a chat
22
+ transcript, one row per step, each with a pending/working/done/error status.
23
+ - **Don't reach for it when:** you want a user or assistant message bubble
24
+ (→ `ScInChatMessage`), a standalone "Using X…" delegation pill
25
+ (→ `ScSubAgent`), the agent's task checklist (→ `ScTodoList`), or just the status
26
+ glyph on its own (→ `ScThinkingStepIcon`).
27
+ - **Four things that will bite you:**
28
+ 1. Despite the name it renders **one row**. There is no `items` prop.
29
+ 2. `showTool` defaults to **`true`** and `toolUsing` defaults to
30
+ **`"Using Catalogix..."`** — a bare `<ScInChatList />` ships Catalogix copy.
31
+ 3. `title` defaults to a **marketing sentence**
32
+ (`"Infrastructure that helps modern brands scale"`).
33
+ 4. It does **not** extend `HTMLAttributes`. Only `className` and `style` get
34
+ through — no `id`, no `onClick`, no `data-*`, no `aria-*`.
35
+
36
+ ---
37
+
38
+ ## 1. How to use it
39
+
40
+ ### Import
41
+
42
+ ```tsx
43
+ import { ScInChatList } from "@streamoid/ui";
44
+ import type { IcListIconState, DescriptionVisibility } from "@streamoid/ui";
45
+ import "@streamoid/ui/dist/index.css"; // once, at your app root
46
+ ```
47
+
48
+ ### Minimal usage
49
+
50
+ ```tsx
51
+ <ScInChatList title="Reading the product feed" iconState="working" showTool={false} />
52
+ ```
53
+
54
+ ### Props
55
+
56
+ | Prop | Type | Default | Notes |
57
+ |---|---|---|---|
58
+ | `title` | `string` | `"Infrastructure that helps modern brands scale"` | ⚠️ Real, very wrong default. Single line only — `nowrap` + ellipsis at 560px. |
59
+ | `description` | `string` | `"Description"` | ⚠️ Real default. Only rendered when `descriptionVisibility === "visible"`. |
60
+ | `descriptionVisibility` | `"no"` \| `"hidden"` \| `"visible"` | `"no"` | `"no"` = no chevron, no description. `"hidden"` = chevron, collapsed. `"visible"` = chevron, expanded. |
61
+ | `leadingIndicator` | `boolean` | `true` | Renders a `ScThinkingStepIcon` in a fixed 20×26 gutter. `false` removes the gutter entirely (rows lose their left alignment). |
62
+ | `iconState` | `IcListIconState` = `"default"` \| `"working"` \| `"completed"` \| `"error"` | `"default"` | Forwarded straight to `ScThinkingStepIcon`. `"working"` spins. |
63
+ | `showSteps` | `boolean` | `false` | Shows the `stepCount` line above the title. |
64
+ | `stepCount` | `string` | `"Step 01:"` | ⚠️ Real default, hardcoded English. You format the number yourself. |
65
+ | `showTool` | `boolean` | `true` | ⚠️ Defaults **on**. Shows the tool pill under the title. |
66
+ | `toolUsing` | `string` | `"Using Catalogix..."` | ⚠️ Real default. Passing `undefined` falls back to it — gate with `showTool`, don't pass `undefined`. |
67
+ | `onToggle` | `() => void` | – | Fires on a click anywhere in the title row. Only wired when `descriptionVisibility` is `"hidden"` or `"visible"`. |
68
+ | `className` | `string` | – | Appended after the internal class. |
69
+ | `style` | `React.CSSProperties` | – | Applied to the root. |
70
+
71
+ ### What renders in each `descriptionVisibility`
72
+
73
+ | Region | `"no"` | `"hidden"` | `"visible"` |
74
+ |---|---|---|---|
75
+ | Chevron | — | ▾ `SiconDown` | ▴ `SiconUp` |
76
+ | Title row click | inert (`cursor: default`) | calls `onToggle` | calls `onToggle` |
77
+ | `description` | not rendered | not rendered | rendered with a dot bullet |
78
+
79
+ ### Recipes
80
+
81
+ ```tsx
82
+ // The canonical transcript: you own the array, the component owns one row
83
+ {steps.map((step, i) => (
84
+ <ScInChatList
85
+ key={step.id ?? i}
86
+ title={step.message}
87
+ iconState={step.status} // "default" | "working" | "completed" | "error"
88
+ showSteps={false}
89
+ descriptionVisibility={step.description ? "visible" : "no"}
90
+ description={step.description}
91
+ showTool={!!step.toolName} // gate the pill…
92
+ toolUsing={`Using ${step.toolName}...`} // …and format it yourself
93
+ leadingIndicator
94
+ />
95
+ ))}
96
+
97
+ // A collapsible step the user can expand
98
+ const [open, setOpen] = useState(false);
99
+ <ScInChatList
100
+ title="Resolved 412 SKUs against the taxonomy"
101
+ description={longExplanation}
102
+ descriptionVisibility={open ? "visible" : "hidden"}
103
+ onToggle={() => setOpen((v) => !v)}
104
+ iconState="completed"
105
+ showTool={false}
106
+ />
107
+
108
+ // Numbered steps
109
+ <ScInChatList showSteps stepCount={`Step ${String(i + 1).padStart(2, "0")}:`} title={s.message} showTool={false} />
110
+
111
+ // The trailing "still working" row while the last step is done
112
+ <ScInChatList title="Planning next steps" iconState="working" descriptionVisibility="no" showTool={false} />
113
+ ```
114
+
115
+ ---
116
+
117
+ ## 2. Where to use it
118
+
119
+ - **The agent chat transcript**, in the reasoning/steps block that sits above the
120
+ assistant's answer. In the live runtime this is
121
+ `stream-agent frontend/src/components/chat/AgentSteps.tsx`, which maps the step
122
+ stream onto one `ScInChatList` per step and interleaves `ScSubAgent` pills and
123
+ plan cards.
124
+ - Anywhere else you have a **stream of short status lines with per-line state** —
125
+ a long-running import, a deploy log — as long as one line per row is what you want.
126
+
127
+ It composes `ScThinkingStepIcon` internally (leading indicator) and nothing else.
128
+ Its tool pill is visually identical to `ScSubAgent`.
129
+
130
+ ---
131
+
132
+ ## 3. When to use it
133
+
134
+ ### Use it when
135
+
136
+ - Each row has **its own lifecycle** (pending → working → completed | error) and you
137
+ want the spinner/tick/cross to be tokenised and consistent.
138
+ - The row's detail is **secondary** and should be collapsible behind a chevron.
139
+ - The row optionally names a **tool** the agent invoked.
140
+
141
+ ### Don't use it — reach for this instead
142
+
143
+ | Situation | Use instead |
144
+ |---|---|
145
+ | A user or assistant chat bubble | `ScInChatMessage` |
146
+ | A standalone "Using <sub-agent>…" pill with no step row around it | `ScSubAgent` |
147
+ | The agent's editable task checklist (toggle/add/delete) | `ScTodoList` |
148
+ | Just the status glyph, e.g. in your own layout | `ScThinkingStepIcon` |
149
+ | A dashboard data row | `ScTableList` |
150
+ | A dropdown menu of options | `ScMenuOptions` inside `ScPopUpMenu` |
151
+ | A multi-line, wrapping paragraph of agent prose | `ScInChatMessage` — this title is `nowrap` and truncates |
152
+
153
+ ### Don't confuse with
154
+
155
+ | You may actually want | Not this |
156
+ |---|---|
157
+ | `ScSubAgent` — the bare "Using X…" pill; a step that *is* a delegation | `ScInChatList` is the step row that can *contain* such a pill |
158
+ | `ScTodoList` — a checklist the **user** mutates | This is a read-only step log |
159
+ | A component that takes a list | It takes **one** step; "List" in the name means "list row" |
160
+
161
+ ---
162
+
163
+ ## 4. Why to use it
164
+
165
+ - **The status vocabulary is already tokenised.** Pending grey, working white spinner,
166
+ success green, error red all come from `--alias-*` tokens via
167
+ `ScThinkingStepIcon`, so a transcript reads identically in dark and light mode.
168
+ - **The 20×26 indicator gutter is fixed**, so a stack of rows keeps its titles
169
+ optically aligned regardless of glyph state — the thing hand-rolled step lists
170
+ always get wrong when the spinner swaps in.
171
+ - **`prefers-reduced-motion` is honoured** for the working spinner, for free.
172
+ - **Truncation is decided once.** Titles are single-line with an ellipsis at 560px,
173
+ so a runaway tool message can never reflow the transcript.
174
+
175
+ ---
176
+
177
+ ## Gotchas
178
+
179
+ **1. It renders one row, not a list.** You map.
180
+
181
+ ```tsx
182
+ // WRONG — there is no items prop; this renders one default row
183
+ <ScInChatList items={steps} />
184
+
185
+ // RIGHT
186
+ {steps.map((s) => <ScInChatList key={s.id} title={s.message} showTool={false} />)}
187
+ ```
188
+
189
+ **2. The tool pill is on by default, and its default text says "Using Catalogix...".**
190
+
191
+ ```tsx
192
+ // WRONG — renders a "Using Catalogix..." pill under your title
193
+ <ScInChatList title="Fetching orders" />
194
+
195
+ // RIGHT
196
+ <ScInChatList title="Fetching orders" showTool={false} />
197
+ ```
198
+
199
+ **3. `toolUsing={undefined}` does not hide the pill** — `undefined` triggers the
200
+ default. Gate with `showTool`.
201
+
202
+ ```tsx
203
+ // WRONG — still shows "Using Catalogix..." when toolName is empty
204
+ <ScInChatList title={s.message} toolUsing={s.toolName ? `Using ${s.toolName}...` : undefined} />
205
+
206
+ // RIGHT
207
+ <ScInChatList
208
+ title={s.message}
209
+ showTool={!!s.toolName}
210
+ toolUsing={s.toolName ? `Using ${s.toolName}...` : undefined}
211
+ />
212
+ ```
213
+
214
+ **4. `title` and `description` have real content defaults.** Omit `title` and you
215
+ ship `"Infrastructure that helps modern brands scale"`; omit `description` while
216
+ expanded and you ship the literal word `"Description"`.
217
+
218
+ **5. `description` is dropped unless `descriptionVisibility === "visible"`.**
219
+ `"hidden"` gives you the chevron but no text — that is the collapsed half of the
220
+ pair, and you must flip the prop in `onToggle`. There is no internal state.
221
+
222
+ **6. The title never wraps.** `.title` is `white-space: nowrap; overflow: hidden;
223
+ text-overflow: ellipsis; max-width: 560px`. Long tool output silently truncates —
224
+ put the long form in `description`, not `title`.
225
+
226
+ **7. The expander is not keyboard accessible.** The clickable title row is a plain
227
+ `div` with an `onClick` — no `role`, no `tabIndex`, no `aria-expanded`. If you need
228
+ keyboard access to the description, don't hide it behind the chevron.
229
+
230
+ **8. Only `className` and `style` pass through.** `IScInChatListProps` does **not**
231
+ extend `HTMLAttributes`, unlike most of the library.
232
+
233
+ ```tsx
234
+ // WRONG — type error; none of these reach the DOM
235
+ <ScInChatList title="x" id="step-1" data-testid="step" onClick={select} />
236
+
237
+ // RIGHT — wrap it
238
+ <div id="step-1" data-testid="step" onClick={select}><ScInChatList title="x" /></div>
239
+ ```
240
+
241
+ **9. `leadingIndicator={false}` removes the gutter, not just the glyph.** The row's
242
+ content shifts 28px left, so mixing indicator-less rows into a stack breaks
243
+ alignment. Use `iconState="default"` (a faint hollow ring) if you want an empty slot.
244
+
245
+ **10. The root is capped at `max-width: 600px`.** In a wider panel the rows will not
246
+ fill the column; override with `className` if that matters.
247
+
248
+ ---
249
+
250
+ ## In the wild
251
+
252
+ Rendered by the **agent runtime**, not by any of the four dashboards — the live call
253
+ site is the chat transcript's steps block in the `stream-agent` repo (the copilot
254
+ widget):
255
+
256
+ ```tsx
257
+ // stream-agent frontend/src/components/chat/AgentSteps.tsx:448
258
+ <ScInChatList
259
+ title={step.message}
260
+ iconState={mapIconState(step.status)}
261
+ showSteps={false}
262
+ descriptionVisibility={step.description ? 'visible' : 'no'}
263
+ description={step.description}
264
+ showTool={!!step.toolName}
265
+ toolUsing={step.toolName ? `Using ${step.toolName}...` : undefined}
266
+ leadingIndicator
267
+ />
268
+ ```
269
+
270
+ ---
271
+
272
+ ## Related
273
+
274
+ - `ScThinkingStepIcon` — the leading glyph; use it alone for a bespoke row layout.
275
+ - `ScSubAgent` — the standalone "Using X…" pill for delegation steps.
276
+ - `ScInChatMessage` — the message bubble the steps block sits above.
277
+ - `ScTodoList` — the interactive checklist, when the user owns the items.
@@ -0,0 +1,205 @@
1
+ ---
2
+ component: ScInChatMessage
3
+ package: "@streamoid/ui"
4
+ category: chat-agent
5
+ status: stable
6
+ renders: div
7
+ tags: [chat, message, bubble, transcript, agent, user, input, output, inchat]
8
+ related: [ScInChatList, ScSubAgent, ScQuickPrompt, ScBriefCard]
9
+ do_not_confuse_with: [ScInChatList, ScInfoPopup, ScBriefCard]
10
+ used_by: [agent]
11
+ ---
12
+
13
+ # ScInChatMessage
14
+
15
+ **A single chat bubble.** One rounded, padded block of 16/24 text: `type="input"` is
16
+ the user's bubble (raised fill, squared bottom-right corner), `type="output"` is the
17
+ agent's (base surface, 1px divider border, fully rounded).
18
+
19
+ ## TL;DR for agents
20
+
21
+ - **Reach for it when:** you need the bubble chrome for one turn of a chat transcript.
22
+ - **Don't reach for it when:** you're rendering the agent's reasoning steps
23
+ (→ `ScInChatList`), a "Using X…" pill (→ `ScSubAgent`), a suggested prompt card
24
+ (→ `ScQuickPrompt`), or **any markdown / block content** — see Gotcha 1.
25
+ - **Three things that will bite you:**
26
+ 1. Children are rendered **inside a `<p>`**. Block elements (markdown, `<div>`,
27
+ lists, code blocks) are invalid there and React will warn / the browser will
28
+ re-parent them.
29
+ 2. `type` defaults to **`"input"`** — the *user* bubble. Agent turns need
30
+ `type="output"` explicitly.
31
+ 3. No avatar, no timestamp, no author, no markdown, no streaming cursor. It is
32
+ purely the bubble.
33
+
34
+ ---
35
+
36
+ ## 1. How to use it
37
+
38
+ ### Import
39
+
40
+ ```tsx
41
+ import { ScInChatMessage } from "@streamoid/ui";
42
+ import "@streamoid/ui/dist/index.css"; // once, at your app root
43
+ ```
44
+
45
+ ### Minimal usage
46
+
47
+ ```tsx
48
+ <ScInChatMessage type="input" text={userMessage} />
49
+ ```
50
+
51
+ ### Props
52
+
53
+ | Prop | Type | Default | Notes |
54
+ |---|---|---|---|
55
+ | `type` | `"input"` \| `"output"` | `"input"` | ⚠️ Defaults to the **user** bubble. `input` = raised fill, bottom-right corner squared to 4px. `output` = base surface + divider border, all corners 18px. |
56
+ | `text` | `string` | – | The bubble text. Rendered only when `children` is not supplied. Omit both and you get an empty `<p>` with full padding (a visible empty bubble). |
57
+ | `children` | `ReactNode` | – | Wins over `text` (`children ?? text`). **Goes inside a `<p>`** — inline content only. |
58
+ | `id` | `string` | – | On the root div. Useful for scroll-to-message anchors. |
59
+ | `className` | `string` | – | Appended after the internal classes. |
60
+ | `...props` | `HTMLAttributes<HTMLDivElement>` | – | `onClick`, `style`, `data-*`, `aria-*` spread onto the root. |
61
+
62
+ ### Recipes
63
+
64
+ ```tsx
65
+ // The two turns
66
+ <ScInChatMessage type="input" text={turn.userText} />
67
+ <ScInChatMessage type="output" text={turn.assistantText} />
68
+
69
+ // Scroll anchor for "jump to this message"
70
+ <ScInChatMessage id={`msg-${turn.id}`} type="input" text={turn.userText} />
71
+
72
+ // Inline emphasis is fine — it stays inside the <p>
73
+ <ScInChatMessage type="output">
74
+ Mapped <strong>412</strong> SKUs. <em>3 need review.</em>
75
+ </ScInChatMessage>
76
+
77
+ // Markdown / block content: use the bubble's tokens, not the bubble
78
+ // (this is what the real runtime does for assistant turns)
79
+ <div className="chat-output-bubble">
80
+ <ReactMarkdown remarkPlugins={[remarkGfm]}>{md}</ReactMarkdown>
81
+ </div>
82
+ ```
83
+
84
+ ---
85
+
86
+ ## 2. Where to use it
87
+
88
+ - **The agent chat transcript**, one per turn. In the live runtime
89
+ (`stream-agent frontend/src/components/chat/MessageBlocks.tsx`) only the
90
+ **user** turn uses it — assistant turns need markdown, lists and code blocks, so
91
+ they are rendered with a bespoke container (see Gotcha 1).
92
+ - Attachments/thumbnails for a user turn are rendered **above** it as siblings, not
93
+ as children.
94
+ - The reasoning steps (`ScInChatList`, `ScSubAgent`) sit between the input bubble and
95
+ the output block.
96
+
97
+ ---
98
+
99
+ ## 3. When to use it
100
+
101
+ ### Use it when
102
+
103
+ - You need the exact product bubble geometry and surface tokens for a **plain-text**
104
+ turn.
105
+ - The content is one paragraph of prose or a short inline-formatted string.
106
+
107
+ ### Don't use it — reach for this instead
108
+
109
+ | Situation | Use instead |
110
+ |---|---|
111
+ | Agent reasoning / tool steps | `ScInChatList` |
112
+ | "Using <sub-agent>…" pill | `ScSubAgent` |
113
+ | Suggested starter prompts | `ScQuickPrompt` |
114
+ | A saved brief / conversation summary card | `ScBriefCard` |
115
+ | Markdown, code blocks, tables, lists | your own container — a `<p>` can't hold them |
116
+ | A hint/help popover in a dashboard | `ScInfoPopup` |
117
+ | A persistent warning strip in a page or sidebar | `CreditWarningBanner` (exported without the `Sc` prefix) |
118
+
119
+ ### Don't confuse with
120
+
121
+ | You may actually want | Not this |
122
+ |---|---|
123
+ | `ScInChatList` — a *step* row with a status glyph and tool pill | This is a message bubble with no status |
124
+ | A bubble that renders markdown | This renders a raw string inside a `<p>` |
125
+ | `type` as an author name | It is the surface variant only; there is no author/avatar concept |
126
+
127
+ ---
128
+
129
+ ## 4. Why to use it
130
+
131
+ - **The asymmetric corner is the product's signature.** `input` squares its
132
+ bottom-right corner to `--radius-xs` while keeping 18px elsewhere; getting that
133
+ wrong is the fastest way to make a chat look off-brand.
134
+ - **Both surfaces are token pairs.** `--alias-surface-subtleraised` vs
135
+ `--alias-surface-base` + `--alias-border-divider` keep the user and agent bubbles
136
+ distinguishable in light mode, where a hand-rolled "slightly grey" bubble collapses
137
+ into the page.
138
+ - **`word-break: break-word`** is already set, so pasted URLs and long IDs cannot
139
+ blow out the transcript width.
140
+ - **`max-width: 600px`** matches every other chat primitive in the family
141
+ (`ScInChatList`, `ScSelectionList`), so a transcript has one measure.
142
+
143
+ ---
144
+
145
+ ## Gotchas
146
+
147
+ **1. Children live inside a `<p>`.** The component always renders
148
+ `<p className={styles.text}>{children ?? text}</p>`.
149
+
150
+ ```tsx
151
+ // WRONG — <div>/<ul>/markdown inside <p>: React warns, the DOM re-parents,
152
+ // and your padding/radius end up on the wrong box
153
+ <ScInChatMessage type="output">
154
+ <ReactMarkdown>{md}</ReactMarkdown>
155
+ </ScInChatMessage>
156
+
157
+ // RIGHT — plain text through the bubble…
158
+ <ScInChatMessage type="output" text={plainText} />
159
+
160
+ // …or your own container for block content
161
+ <div className="my-output-bubble"><ReactMarkdown>{md}</ReactMarkdown></div>
162
+ ```
163
+
164
+ **2. `type` defaults to `"input"`.** Forget it on an assistant turn and the agent's
165
+ reply is styled as if the user said it.
166
+
167
+ **3. `text` has no default.** `<ScInChatMessage />` renders a fully padded, bordered,
168
+ **empty** bubble rather than nothing. Guard on empty content yourself.
169
+
170
+ **4. `children` silently wins over `text`.** Passing both is not an error; `text` is
171
+ just ignored.
172
+
173
+ **5. There is no author, avatar, timestamp or "typing" state.** Anything a real
174
+ transcript needs beyond the bubble is your composition problem — put it in sibling
175
+ elements, not children.
176
+
177
+ **6. Streaming text reflows the whole bubble.** The bubble is `max-width: 600px` with
178
+ no min-height, so a token-by-token stream grows it line by line. If you need a stable
179
+ box during streaming, set a `min-height` via `className`.
180
+
181
+ **7. The font size is fixed at 16/24.** There is no `size` prop; `className` overrides
182
+ have to target the inner `<p>`, which is a CSS-module class you don't own. Prefer
183
+ wrapping in a container with your own text element if you need a different scale.
184
+
185
+ ---
186
+
187
+ ## In the wild
188
+
189
+ Rendered by the **agent runtime**, not by any of the four dashboards — the live call
190
+ site is the chat transcript's message block in the `stream-agent` repo (the copilot
191
+ widget):
192
+
193
+ ```tsx
194
+ // stream-agent frontend/src/components/chat/MessageBlocks.tsx:291
195
+ <ScInChatMessage type="input" text={content} />
196
+ ```
197
+
198
+ ---
199
+
200
+ ## Related
201
+
202
+ - `ScInChatList` — the reasoning-step row that sits between the two bubbles.
203
+ - `ScSubAgent` — the "Using X…" delegation pill.
204
+ - `ScQuickPrompt` — the suggested-prompt card shown in an empty transcript.
205
+ - `ScBriefCard` — a saved-brief card in the chat surface.