@streamoid/ui 0.6.16 → 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 +43 -37
  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,305 @@
1
+ ---
2
+ component: CreditWarningBanner
3
+ package: "@streamoid/ui"
4
+ category: sidebar
5
+ status: stable
6
+ renders: div | button (collapsed)
7
+ tags: [credits, low-credits, warning, banner, danger, buy-credits, sidebar-footer, dismiss]
8
+ related: [StreamoidSidebar, ScArtifaxSidebar, ScCreditsUsageCard, ScPlanCard, ScBadges]
9
+ do_not_confuse_with: [ScCreditsUsageCard, ScGuide, ScBadges, ScInfoPopup]
10
+ used_by: [cxo, photogenix, artifax]
11
+ required_props: [availableCredits, remainingPct, level, onBuyCredits]
12
+ ---
13
+
14
+ # CreditWarningBanner
15
+
16
+ **The low-credits alert that sits in a sidebar's pre-footer slot.** Expanded: a tinted
17
+ card with a warning triangle, "Low Credits", a dismiss ✕, and the sentence
18
+ "Only *N* credits (*P*%) remaining. **Buy credits** to avoid interruptions."
19
+ Collapsed: a 40×40 tinted square holding just the triangle.
20
+
21
+ ⚠️ **The export is `CreditWarningBanner`, not `ScCreditWarningBanner`.** It is the one
22
+ component in this family without the `Sc` prefix — the component catalog names it
23
+ wrongly. `import { ScCreditWarningBanner }` is `undefined`.
24
+
25
+ ## TL;DR for agents
26
+
27
+ - **Reach for it when:** you need the "you're nearly out of credits" nudge in a
28
+ sidebar rail, in either expanded or collapsed form.
29
+ - **Don't reach for it when:** you want the credits **meter** on a billing page
30
+ (→ `ScCreditsUsageCard`), a generic callout (→ `ScGuide`), or a status chip
31
+ (→ `ScBadges`).
32
+ - **Four things that will bite you:**
33
+ 1. The export name has **no `Sc` prefix**.
34
+ 2. It owns its own dismiss state: ✕ makes it return `null` **forever**, with no
35
+ callback and no way to reopen it except remounting with a new `key`.
36
+ 3. `remainingPct` is printed **raw** — no rounding, no clamping. Pass
37
+ `Math.round(...)` or you ship `(33.33333333333333%)`.
38
+ 4. `expanded` defaults to **`true`**; in a collapsed rail you must pass
39
+ `expanded={false}` explicitly.
40
+
41
+ ---
42
+
43
+ ## 1. How to use it
44
+
45
+ ### Import
46
+
47
+ ```tsx
48
+ import { CreditWarningBanner } from "@streamoid/ui";
49
+ import "@streamoid/ui/dist/index.css"; // once, at your app root
50
+ ```
51
+
52
+ ### Minimal usage
53
+
54
+ ```tsx
55
+ <CreditWarningBanner
56
+ availableCredits={1200}
57
+ remainingPct={4}
58
+ level="danger"
59
+ onBuyCredits={() => navigate("/settings/billing")}
60
+ />
61
+ ```
62
+
63
+ ### Props
64
+
65
+ | Prop | Type | Default | Notes |
66
+ |---|---|---|---|
67
+ | `availableCredits` | `number` | — | **Required.** Rendered via `.toLocaleString()` — thousands separators come from the browser locale. |
68
+ | `remainingPct` | `number` | — | **Required.** Printed verbatim inside `(…%)`. **Round it yourself.** |
69
+ | `level` | `"warning" \| "danger"` | — | **Required — there is no default.** `warning` = orange tint + `--primitives-warning-400`; `danger` = red tint + `--primitives-error-400`. (Both sidebar wrappers default it to `"danger"`; calling this component directly does not.) |
70
+ | `onBuyCredits` | `() => void` | — | **Required.** The underlined "Buy credits" link, and the collapsed square's fallback click. |
71
+ | `expanded` | `boolean` | `true` | ⚠️ Real default. `false` → the 40×40 icon-only square. |
72
+ | `onCollapsedClick` | `() => void` | `onBuyCredits` | ⚠️ Collapsed square click. Omit it and clicking the square **navigates to billing**; CXO passes the sidebar's `onToggle` so it expands the rail instead. |
73
+
74
+ ### What renders in each state
75
+
76
+ | Region | `expanded` (default) | `expanded={false}` |
77
+ |---|---|---|
78
+ | Root | `div`, `padding: 16px 8px`, full width | **`button`**, 40×40, `aria-label="Show low credits warning"` |
79
+ | Card | tinted bg + 0.5px tinted border, 12px radius, 12px padding | same tint, `radius-xl` |
80
+ | Header | triangle icon + "Low Credits" (12px/600) + ✕ | — |
81
+ | Body | "Only *N* credits (*P*%) remaining. Buy credits to avoid interruptions." | — |
82
+ | Icon | 16×16 triangle, `strokeWidth` 1.25 | same 16×16 triangle |
83
+ | Dismiss | ✕ button, `aria-label="Dismiss low credits warning"` | **none — cannot be dismissed** |
84
+
85
+ ### Recipes
86
+
87
+ ```tsx
88
+ // The standard host wiring: StreamoidSidebar's pre-footer, both rails
89
+ <StreamoidSidebar
90
+ expanded={sidebarExpanded}
91
+ onToggle={onToggle}
92
+ preFooterContent={
93
+ creditWarning ? (
94
+ <CreditWarningBanner
95
+ availableCredits={creditWarning.availableCredits}
96
+ remainingPct={creditWarning.remainingPct}
97
+ level={creditWarning.level}
98
+ expanded={sidebarExpanded} // MUST track the rail
99
+ onBuyCredits={() => navigate("/settings/billing")}
100
+ onCollapsedClick={onToggle} // expand the rail, don't jump to billing
101
+ />
102
+ ) : undefined
103
+ }
104
+ /* … */
105
+ />
106
+
107
+ // Deriving the props safely
108
+ const pct = total > 0 ? Math.max(0, Math.min(100, (available / total) * 100)) : 0;
109
+ <CreditWarningBanner
110
+ availableCredits={available}
111
+ remainingPct={Math.round(pct)} // ROUND — the component won't
112
+ level={pct < 5 ? "danger" : "warning"}
113
+ onBuyCredits={goBilling}
114
+ expanded={expanded}
115
+ onCollapsedClick={onToggle}
116
+ />
117
+
118
+ // Bringing it back after the user dismissed it (e.g. credits dropped further)
119
+ <CreditWarningBanner key={`credits-${level}-${bucket}`} … />
120
+
121
+ // Through a sidebar that owns it for you (level defaults to "danger" there)
122
+ <ScArtifaxSidebar
123
+ creditWarning={{ availableCredits: 120, remainingPct: 4, onBuyCredits: goBilling }}
124
+ /* … */
125
+ />
126
+ ```
127
+
128
+ ---
129
+
130
+ ## 2. Where to use it
131
+
132
+ - **`StreamoidSidebar`'s `preFooterContent`** — CXO
133
+ (`src/app/components/app-sidebar.tsx:986`) does this directly, and is the only
134
+ **live** host render site. Photogenix has a local `LowCreditsBanner` wrapper that
135
+ computes the percentage, but it is currently **not rendered**: it is imported by
136
+ `DashboardContent.tsx` without being used, and the shipped rail hand-rolls its own
137
+ tinted div in `Sidebar.tsx` instead. Reuse the wrapper rather than the hand-roll.
138
+ - **`ScArtifaxSidebar`'s `creditWarning` prop** (Artifax's live wiring) and
139
+ **`ScCatalogixSidebar`'s `creditWarning` prop** (that wrapper is `status: legacy`
140
+ and unused) — both render this component internally, so don't nest a second one.
141
+ - Catalogix's current shell renders no credit banner at all.
142
+ - Its expanded padding (`16px 8px`) assumes it sits inside a 256px rail; the collapsed
143
+ form assumes a 56px rail.
144
+ - **Not** for page-level billing surfaces — that's `ScCreditsUsageCard` /
145
+ `ScPlanDetailsCard`.
146
+
147
+ ---
148
+
149
+ ## 3. When to use it
150
+
151
+ ### Use it when
152
+
153
+ - Credits are low enough that the user should act **now**, and the message should
154
+ follow them across every screen (hence: the sidebar).
155
+ - You want the same alert to survive a rail collapse as a compact square.
156
+ - The only action is "buy credits".
157
+
158
+ ### Don't use it — reach for this instead
159
+
160
+ | Situation | Use instead |
161
+ |---|---|
162
+ | Credits **remaining / usage meter** on a billing or settings page | `ScCreditsUsageCard` / `ScCreditsUsageCardMobile` |
163
+ | Current-plan summary, upgrade CTA | `ScPlanDetailsCard` / `ScPlanCard` |
164
+ | A generic onboarding/informational callout | `ScGuide` |
165
+ | A non-interactive status or count chip | `ScBadges` |
166
+ | Contextual "?" help | `ScInfoPopup` |
167
+ | A blocking "out of credits" dialog | `ScModal` + `ScButton` |
168
+ | A free-plan upsell CTA in the rail | a plain `ScButton` in `preFooterContent` (what Photogenix does) |
169
+
170
+ ### Don't confuse with
171
+
172
+ | You may actually want | Not this |
173
+ |---|---|
174
+ | `ScCreditsUsageCard` — the billing-page meter with usage breakdown | This is a small red/orange sidebar nudge |
175
+ | `ScGuide` — heading + body callout card, tokenised | This one reads `--primitives-*` directly and cannot re-theme |
176
+ | `ScBadges` — a chip | This is a dismissible card with an action |
177
+ | `ScCreditWarningBanner` — **does not exist** | The export is `CreditWarningBanner` |
178
+
179
+ ---
180
+
181
+ ## 4. Why to use it
182
+
183
+ - **Both rail forms in one component.** The collapsed 40×40 square keeps the exact
184
+ tint and icon of the expanded card, so the warning never disappears when the user
185
+ collapses the sidebar.
186
+ - **A consistent severity vocabulary.** `level` maps to the same warning/error hues
187
+ used everywhere else (`--primitives-warning-400` / `--primitives-error-400`) with
188
+ matching 8%-alpha fills and 32%-alpha strokes, instead of every app picking its own red.
189
+ - **Correct button semantics for the two actions.** The dismiss ✕, the "Buy credits"
190
+ link and the collapsed square are all real `<button>`s with `aria-label`s; the
191
+ triangle is `aria-hidden`.
192
+ - **Locale-aware numbers.** `availableCredits.toLocaleString()` so "1,200" not "1200".
193
+ - **It's what the sidebars already render.** Using it directly keeps a host's
194
+ hand-rolled banner from drifting away from Artifax's and Catalogix's.
195
+
196
+ ---
197
+
198
+ ## Gotchas
199
+
200
+ **1. The export has no `Sc` prefix.**
201
+
202
+ ```tsx
203
+ // WRONG — undefined; the catalog's name for it is incorrect
204
+ import { ScCreditWarningBanner } from "@streamoid/ui";
205
+
206
+ // RIGHT
207
+ import { CreditWarningBanner } from "@streamoid/ui";
208
+ ```
209
+
210
+ **2. Dismissal is internal and permanent.** `const [dismissed, setDismissed] = useState(false)`
211
+ and `if (dismissed) return null`. There is no `onDismiss`, no `dismissed` prop, no
212
+ `persist` option. Once the user clicks ✕ the banner is gone for the lifetime of that
213
+ component instance — even if credits drop to zero.
214
+
215
+ ```tsx
216
+ // If it must be able to come back, change the key
217
+ <CreditWarningBanner key={`credits-${severityBucket}`} … />
218
+ ```
219
+
220
+ **3. `remainingPct` is printed unformatted.** Photogenix's own wrapper computes
221
+ `(availableCredits / totalCredits) * 100` without rounding, which renders as
222
+ `(33.33333333333333%)`. Round (and clamp) at the call site.
223
+
224
+ **4. `expanded` defaults to `true`.** In a collapsed rail you must thread the rail
225
+ state through, or you get the full 256px-wide card inside a 56px rail.
226
+
227
+ **5. `onCollapsedClick` falls back to `onBuyCredits`.** Clicking the little square
228
+ then navigates to billing, which is not what a "show me the warning" affordance should
229
+ do. CXO passes the sidebar's `onToggle`, and `ScCatalogixSidebar` defaults its
230
+ `creditWarning.onCollapsedClick` to `onToggle` — but `ScArtifaxSidebar` has **no**
231
+ `onCollapsedClick` field on its `creditWarning` object at all, so in Artifax the
232
+ collapsed square always jumps to billing.
233
+
234
+ **6. It reads `--primitives-*`, not `--alias-*`.** `--primitives-warning-400` /
235
+ `--primitives-error-400` plus literal `rgba(255,165,0,…)` / `rgba(255,0,0,…)` fills
236
+ and borders. It is the one component in this family that bypasses the semantic token
237
+ layer, so it does **not** re-theme with light mode the way the rest of the DS does.
238
+
239
+ **7. All copy is hardcoded English.** "Low Credits", "Only {n} credits ({p}%)
240
+ remaining.", "Buy credits", "to avoid interruptions.", plus the
241
+ `"Dismiss low credits warning"` / `"Show low credits warning"` aria-labels. No label
242
+ props — not usable on a localised surface without changing the DS.
243
+
244
+ **8. `level` is required, with no default.** Rendering it via a sidebar's
245
+ `creditWarning` prop gets you `"danger"` by default; calling the component directly
246
+ does not, and TypeScript will (correctly) reject the omission.
247
+
248
+ **9. The collapsed form can't be dismissed.** No ✕ in that branch — so a user who
249
+ collapses the rail is stuck with the square until they expand and dismiss.
250
+
251
+ **10. `toLocaleString()` is locale-dependent.** Server-rendered and client-rendered
252
+ output can differ (hydration warnings) and screenshot tests can vary by CI locale.
253
+
254
+ **11. It needs Tailwind.** The layout uses `flex`, `shrink-0`, `w-full`, `min-w-0`,
255
+ `flex-1`, `items-center`, `cursor-pointer`, `underline`, `transition-opacity`,
256
+ `hover:opacity-90`. `@streamoid/ui/dist/index.css` does **not** ship those utilities —
257
+ your app must (all four hosts do).
258
+
259
+ **12. Fixed geometry.** Collapsed square 40×40, icons 16×16, ✕ hit-area 16×16 (small
260
+ for touch), body text a literal `fontSize: 12`.
261
+
262
+ ---
263
+
264
+ ## In the wild
265
+
266
+ ```tsx
267
+ // cxo-dashboard src/app/components/app-sidebar.tsx:986 (inside StreamoidSidebar's preFooterContent)
268
+ <CreditWarningBanner
269
+ availableCredits={creditWarning.availableCredits}
270
+ remainingPct={creditWarning.remainingPct}
271
+ level={creditWarning.level}
272
+ expanded={sidebarExpanded}
273
+ onBuyCredits={handleBuyCreditsNavigation}
274
+ onCollapsedClick={onToggle}
275
+ />
276
+ ```
277
+
278
+ ```tsx
279
+ // photogenix_v2 dashboard/client/src/components/layout/LowCreditsBanner.tsx:27
280
+ // (a real wrapper, but currently unrendered — see §2; exercised only by
281
+ // dashboard/tests/low-credits-banner.vitest.tsx)
282
+ <CreditWarningBanner
283
+ availableCredits={availableCredits}
284
+ remainingPct={remainingPct} // NB: unrounded float — see Gotcha 3
285
+ level={level}
286
+ onBuyCredits={onBuyCredits}
287
+ expanded={expanded}
288
+ onCollapsedClick={onCollapsedClick}
289
+ />
290
+ ```
291
+
292
+ Artifax reaches it indirectly, through `ScArtifaxSidebar`'s `creditWarning` prop
293
+ (`artifax packages/shared/src/components/DashboardSidebar.tsx:680`). Catalogix's shell
294
+ renders no banner today.
295
+
296
+ ---
297
+
298
+ ## Related
299
+
300
+ - `StreamoidSidebar` — pass this as `preFooterContent`, threading `expanded`.
301
+ - `ScArtifaxSidebar` / `ScCatalogixSidebar` — render it for you from `creditWarning`.
302
+ - `ScCreditsUsageCard` — the billing-page credits meter (tokenised, non-dismissible).
303
+ - `ScPlanCard` / `ScPlanDetailsCard` — where "Buy credits" usually lands.
304
+ - `ScGuide` — the tokenised generic callout card.
305
+ - `@streamoid/icons` — `SiconClose` is the dismiss glyph; the warning triangle is an inline SVG in this component.
@@ -0,0 +1,222 @@
1
+ ---
2
+ component: InvoiceHistoryMobile
3
+ package: "@streamoid/ui"
4
+ category: mobile
5
+ status: stable
6
+ renders: div
7
+ tags: [mobile, billing, invoice, history, row, list-item, amount, cxo]
8
+ related: [UsageHistoryMobile, ScBillingHistoryTableList, ScBillingHistoryHeader, ScInvoiceHistoryMobile]
9
+ do_not_confuse_with: [ScInvoiceHistoryMobile, UsageHistoryMobile, ScBillingHistoryTableList, ScTableListMobile]
10
+ used_by: [cxo]
11
+ ---
12
+
13
+ # InvoiceHistoryMobile
14
+
15
+ **One invoice row in CXO's mobile billing list.** Invoice id over a date on the left,
16
+ a green amount right-aligned, and a 0.5px bottom border so a stack of them reads as a
17
+ list. Note the export name: **no `Sc` prefix** — it and `UsageHistoryMobile` are the
18
+ only two components in the mobile family without one.
19
+
20
+ ## TL;DR for agents
21
+
22
+ - **Reach for it when:** you are rendering the "Invoice history" tab of a mobile
23
+ billing screen, one component per invoice.
24
+ - **Don't reach for it when:** you're on desktop (→ `ScBillingHistoryTableList` +
25
+ `ScBillingHistoryHeader`) or the row is a credit-usage log (→ `UsageHistoryMobile`).
26
+ - **Four things that will bite you:**
27
+ 1. **The export is `InvoiceHistoryMobile`, not `ScInvoiceHistoryMobile`.** A
28
+ `ScInvoiceHistoryMobile` *does* exist in the source tree
29
+ (`src/SC-InvoiceHistory-Mobile/`) but it is **not exported** — see "Don't
30
+ confuse with".
31
+ 2. **No `onClick`, and no props spread.** `className` is the only escape hatch;
32
+ you cannot attach a handler, `key`-adjacent `data-*`, `style`, or `aria-*`.
33
+ Wrap it if the row must be tappable.
34
+ 3. **The amount is always success-green**, including refunds and zero.
35
+ 4. All three text props have demo defaults (`"# INV-2800-2026"`, `"Nov 9th, 2025"`,
36
+ `"₹320.89"` — a rupee amount).
37
+
38
+ ---
39
+
40
+ ## 1. How to use it
41
+
42
+ ### Import
43
+
44
+ ```tsx
45
+ import { InvoiceHistoryMobile } from "@streamoid/ui";
46
+ import "@streamoid/ui/dist/index.css"; // once, at your app root
47
+ ```
48
+
49
+ ### Minimal usage
50
+
51
+ ```tsx
52
+ {invoices.map((inv) => (
53
+ <InvoiceHistoryMobile
54
+ key={inv.id}
55
+ invoiceId={`# ${inv.number}`}
56
+ date={formatDate(inv.createdAt)}
57
+ amount={`$${inv.amountPaid.toFixed(2)}`}
58
+ />
59
+ ))}
60
+ ```
61
+
62
+ ### Props
63
+
64
+ | Prop | Type | Default | Notes |
65
+ |---|---|---|---|
66
+ | `invoiceId` | `string` | `"# INV-2800-2026"` | ⚠️ Demo default. 16px primary line. You supply the `#` — the component adds nothing. Truncates with ellipsis. |
67
+ | `date` | `string` | `"Nov 9th, 2025"` | ⚠️ Demo default. 14px tertiary sub-line. Pre-formatted string; no date parsing. |
68
+ | `amount` | `string` | `"₹320.89"` | ⚠️ Demo default **in rupees**. 16px/600, always `--alias-text-and-icons-success` green. You supply the currency symbol. |
69
+ | `className` | `string` | – | Appended after internal classes (safely — uses `className ?? ""`). **The only extra prop it accepts.** |
70
+
71
+ That is the whole API. There is no `onClick`, no `...props`, no `status`, no icon.
72
+
73
+ ### Recipes
74
+
75
+ ```tsx
76
+ // Make the row tappable — the component itself has no onClick
77
+ <div role="button" tabIndex={0} onClick={() => openInvoice(inv)} className="cursor-pointer">
78
+ <InvoiceHistoryMobile
79
+ invoiceId={`# ${inv.number}`}
80
+ date={formatDate(inv.createdAt)}
81
+ amount={`$${inv.amountPaid.toFixed(2)}`}
82
+ />
83
+ </div>
84
+
85
+ // Empty state — render your own; this component has no zero/empty mode
86
+ {invoices.length === 0
87
+ ? <p>No invoices found</p>
88
+ : invoices.map((inv) => <InvoiceHistoryMobile key={inv.id} {...toRow(inv)} />)}
89
+
90
+ // Stripe amounts arrive in cents
91
+ <InvoiceHistoryMobile
92
+ invoiceId={`# ${inv.meta?.stripeInvoiceId ?? inv._id}`}
93
+ date={formatDate(inv.createdAt)}
94
+ amount={inv.amountPaid != null ? `$${inv.amountPaid.toFixed(2)}` : `$${(inv.amount / 100).toFixed(2)}`}
95
+ />
96
+ ```
97
+
98
+ ---
99
+
100
+ ## 2. Where to use it
101
+
102
+ - **CXO mobile billing screen**, inside the "Invoice history" tab of the
103
+ `ScTabSwitcher`, below `ScPlanDetailsCardMobile` and `ScCreditsUsageCardMobile`.
104
+ - Any narrow scrolling list of "document + date + money" rows.
105
+
106
+ The row draws its own bottom border, so stack them with **no gap** and no dividers of
107
+ your own. It composes nothing from the DS.
108
+
109
+ ---
110
+
111
+ ## 3. When to use it
112
+
113
+ ### Use it when
114
+
115
+ - The viewport is mobile and each invoice is a full-width two-line row.
116
+ - You already have id, date and amount as display strings.
117
+ - The list is read-only, or you own the tap target yourself (wrapper div).
118
+
119
+ ### Don't use it — reach for this instead
120
+
121
+ | Situation | Use instead |
122
+ |---|---|
123
+ | Desktop billing history table | `ScBillingHistoryHeader` + `ScBillingHistoryTableList` |
124
+ | Credit-usage / debit log rows on mobile | `UsageHistoryMobile` |
125
+ | Desktop credit/usage log table | `ScBillingLogsTableHeader` + `ScBillingLogsTableList` |
126
+ | A generic member/user row on mobile | `ScTableListMobile` |
127
+ | Referral rows on mobile | `ScReferralCardMobile` |
128
+ | A row that must be clickable *with* DS-provided semantics | none of these — wrap it, or use `ScTableListMobile` which has `onRowClick` |
129
+
130
+ ### Don't confuse with
131
+
132
+ | You may actually want | Not this |
133
+ |---|---|
134
+ | `ScInvoiceHistoryMobile` in `src/SC-InvoiceHistory-Mobile/` — an earlier, near-identical copy with `invoiceNumber` instead of `invoiceId`, plus `onClick` and a props spread | It is **not exported** from `index.ts`, its CSS is **not** in `dist/index.css`, and `IScInvoiceHistoryMobileProps` is absent from `dist/index.d.ts`. Importing it will fail. Use `InvoiceHistoryMobile`. |
135
+ | `UsageHistoryMobile` — same chrome, but two rows of two values and a **red** figure | Invoices are green money in; usage is red credits out |
136
+ | `ScBillingHistoryTableList` — the desktop row | Different metrics, header component required |
137
+
138
+ ---
139
+
140
+ ## 4. Why to use it
141
+
142
+ - **The truncation math is done.** `flex: 1; min-width: 0` on the text column with
143
+ `ellipsis` on both lines, and `flex-shrink: 0` on the amount, so a long invoice id
144
+ never pushes the money off-screen — the single thing hand-rolled money rows get wrong.
145
+ - **Self-dividing.** The bottom border is part of the row, so you never end up with a
146
+ trailing divider or a double line between sections.
147
+ - **Correct tokens.** It uses the real `--alias-text-and-icons-*` names (unlike much
148
+ of the mobile family), so it genuinely flips light/dark.
149
+ - **Money semantics are consistent** with `UsageHistoryMobile`: green = money/credits
150
+ in, red = credits out, tertiary grey = context.
151
+
152
+ ---
153
+
154
+ ## Gotchas
155
+
156
+ **1. The name has no `Sc` prefix.** Autocomplete for `Sc…` will not find it.
157
+
158
+ ```tsx
159
+ // WRONG — not exported
160
+ import { ScInvoiceHistoryMobile } from "@streamoid/ui";
161
+
162
+ // RIGHT
163
+ import { InvoiceHistoryMobile } from "@streamoid/ui";
164
+ ```
165
+
166
+ **2. No props spread at all.** The signature is
167
+ `({ invoiceId, date, amount, className })` — nothing else reaches the DOM.
168
+
169
+ ```tsx
170
+ // SILENTLY IGNORED — onClick, style and data-* never land anywhere
171
+ <InvoiceHistoryMobile invoiceId="# 1" onClick={open} style={{ opacity: 0.5 }} data-id="1" />
172
+
173
+ // RIGHT — wrap it
174
+ <div onClick={open} data-id="1"><InvoiceHistoryMobile invoiceId="# 1" /></div>
175
+ ```
176
+
177
+ (In TypeScript the extra props are a compile error; in a plain-JS host they are
178
+ silently dropped.)
179
+
180
+ **3. The amount is unconditionally green.** `--alias-text-and-icons-success` is
181
+ hardcoded, so refunds, credit notes and `$0.00` all read as positive.
182
+
183
+ **4. Demo defaults, including a rupee amount.** Rendering it bare gives
184
+ `# INV-2800-2026 / Nov 9th, 2025 / ₹320.89`, which looks like real data.
185
+
186
+ **5. Nothing is formatted for you.** No currency, no locale grouping, no date parsing,
187
+ no `#` prefix. Three strings in, three strings out.
188
+
189
+ **6. No status.** Paid / open / void / failed cannot be expressed. If you need it,
190
+ put it in `invoiceId` or `date`, or move to a row component that has a badge.
191
+
192
+ **7. `align-items: flex-start`** on the root, so the amount aligns to the **top** of
193
+ the row, level with `invoiceId`, not vertically centred.
194
+
195
+ ---
196
+
197
+ ## In the wild
198
+
199
+ ```tsx
200
+ // cxo-dashboard src/app/components/mobile-billing-content.tsx:231
201
+ <InvoiceHistoryMobile
202
+ key={inv._id}
203
+ invoiceId={`# ${inv.meta?.stripeInvoiceId ?? inv._id}`}
204
+ date={formatDate(inv.createdAt)}
205
+ amount={
206
+ inv.amountPaid != null
207
+ ? `$${inv.amountPaid.toFixed(2)}`
208
+ : `$${(inv.amount / 100).toFixed(2)}`
209
+ }
210
+ />
211
+ ```
212
+
213
+ ---
214
+
215
+ ## Related
216
+
217
+ - `UsageHistoryMobile` — the sibling row for the "Usage history" tab.
218
+ - `ScInvoiceHistoryMobile` (`src/SC-InvoiceHistory-Mobile/`) — the unexported earlier
219
+ copy; do not import it.
220
+ - `ScBillingHistoryHeader` / `ScBillingHistoryTableList` — the desktop table.
221
+ - `ScPlanDetailsCardMobile` / `ScCreditsUsageCardMobile` — the cards above the tabs.
222
+ - `ScTabSwitcher` / `ScTabComp` — what toggles invoice vs usage.