@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.
- package/README.md +35 -18
- package/dist/docs/AGENTS.md +321 -0
- package/dist/docs/CreditWarningBanner.md +305 -0
- package/dist/docs/InvoiceHistoryMobile.md +222 -0
- package/dist/docs/ScAccess.md +259 -0
- package/dist/docs/ScAppCard.md +244 -0
- package/dist/docs/ScAppCardForCopilot.md +230 -0
- package/dist/docs/ScAppCardV3.md +273 -0
- package/dist/docs/ScAppField.md +308 -0
- package/dist/docs/ScAppListingCard.md +271 -0
- package/dist/docs/ScAppSwitchPanel.md +286 -0
- package/dist/docs/ScAppcardLogos.md +226 -0
- package/dist/docs/ScArtifaxInvite.md +262 -0
- package/dist/docs/ScArtifaxSidebar.md +330 -0
- package/dist/docs/ScAskAgentButton.md +307 -0
- package/dist/docs/ScBadges.md +261 -0
- package/dist/docs/ScBeacon.md +244 -0
- package/dist/docs/ScBillingHistoryHeader.md +210 -0
- package/dist/docs/ScBillingHistoryTableList.md +243 -0
- package/dist/docs/ScBillingLogsTableHeader.md +212 -0
- package/dist/docs/ScBillingLogsTableList.md +251 -0
- package/dist/docs/ScBriefCard.md +255 -0
- package/dist/docs/ScButton.md +251 -0
- package/dist/docs/ScCalendar.md +268 -0
- package/dist/docs/ScCalendarDateComps.md +264 -0
- package/dist/docs/ScCatalogixInvite.md +345 -0
- package/dist/docs/ScCatalogixSidebar.md +337 -0
- package/dist/docs/ScCatalogixStoreHeader.md +246 -0
- package/dist/docs/ScCatalogixStoreTableList.md +316 -0
- package/dist/docs/ScCheckField.md +233 -0
- package/dist/docs/ScCheckbox.md +272 -0
- package/dist/docs/ScCounter.md +235 -0
- package/dist/docs/ScCreditsUsageCard.md +247 -0
- package/dist/docs/ScCreditsUsageCardMobile.md +224 -0
- package/dist/docs/ScDefaultCard.md +269 -0
- package/dist/docs/ScDp.md +245 -0
- package/dist/docs/ScDrawer.md +318 -0
- package/dist/docs/ScFieldButton.md +255 -0
- package/dist/docs/ScFileField.md +268 -0
- package/dist/docs/ScGoogleSignIn.md +250 -0
- package/dist/docs/ScGuide.md +278 -0
- package/dist/docs/ScHDivider.md +213 -0
- package/dist/docs/ScHeader.md +222 -0
- package/dist/docs/ScImageField.md +253 -0
- package/dist/docs/ScInChatList.md +277 -0
- package/dist/docs/ScInChatMessage.md +205 -0
- package/dist/docs/ScInfoPopup.md +248 -0
- package/dist/docs/ScIntialProfileCover.md +233 -0
- package/dist/docs/ScInvoiceHistoryMobile.md +187 -0
- package/dist/docs/ScLogoUnit.md +232 -0
- package/dist/docs/ScMappingCard.md +241 -0
- package/dist/docs/ScMediaApproval.md +301 -0
- package/dist/docs/ScMediaSelect.md +310 -0
- package/dist/docs/ScMenuOptions.md +308 -0
- package/dist/docs/ScMobileBottomAction.md +252 -0
- package/dist/docs/ScMobileTopNav.md +279 -0
- package/dist/docs/ScModal.md +291 -0
- package/dist/docs/ScOnlyField.md +302 -0
- package/dist/docs/ScOnlyIcon.md +213 -0
- package/dist/docs/ScPagination.md +284 -0
- package/dist/docs/ScPairtext.md +287 -0
- package/dist/docs/ScPendingAction.md +238 -0
- package/dist/docs/ScPhtogenixInvite.md +275 -0
- package/dist/docs/ScPlanCard.md +302 -0
- package/dist/docs/ScPlanComparison.md +264 -0
- package/dist/docs/ScPlanDetailsCard.md +246 -0
- package/dist/docs/ScPlanDetailsCardMobile.md +240 -0
- package/dist/docs/ScPopUpMenu.md +224 -0
- package/dist/docs/ScProfile.md +234 -0
- package/dist/docs/ScProfileImageUpdate.md +261 -0
- package/dist/docs/ScProfileOptions.md +245 -0
- package/dist/docs/ScProfilePopup.md +396 -0
- package/dist/docs/ScProfileSettingsComp.md +250 -0
- package/dist/docs/ScProfileV2Mobile.md +216 -0
- package/dist/docs/ScProgressBar.md +267 -0
- package/dist/docs/ScQuickPrompt.md +277 -0
- package/dist/docs/ScRadio.md +228 -0
- package/dist/docs/ScReferralCardMobile.md +226 -0
- package/dist/docs/ScReferralTableHeader.md +260 -0
- package/dist/docs/ScReferralTableList.md +293 -0
- package/dist/docs/ScRole.md +226 -0
- package/dist/docs/ScRoleMobile.md +199 -0
- package/dist/docs/ScSelect.md +270 -0
- package/dist/docs/ScSelection.md +256 -0
- package/dist/docs/ScSelectionList.md +272 -0
- package/dist/docs/ScSelectionPill.md +240 -0
- package/dist/docs/ScSelectionPillGroup.md +302 -0
- package/dist/docs/ScSettingsNav.md +212 -0
- package/dist/docs/ScSettingsTabComp.md +260 -0
- package/dist/docs/ScSideBarLogoUnit.md +340 -0
- package/dist/docs/ScSidebar.md +243 -0
- package/dist/docs/ScSidebarIcons.md +232 -0
- package/dist/docs/ScSidebarMenu.md +283 -0
- package/dist/docs/ScSidebarProfile.md +231 -0
- package/dist/docs/ScSidebarSwitchMenu.md +258 -0
- package/dist/docs/ScSlider.md +194 -0
- package/dist/docs/ScStoreCard.md +252 -0
- package/dist/docs/ScStrLogo.md +253 -0
- package/dist/docs/ScStreamoidWordmark.md +302 -0
- package/dist/docs/ScSubAgent.md +226 -0
- package/dist/docs/ScTabComp.md +308 -0
- package/dist/docs/ScTabField.md +258 -0
- package/dist/docs/ScTabSwitcher.md +307 -0
- package/dist/docs/ScTableHeader.md +261 -0
- package/dist/docs/ScTableList.md +301 -0
- package/dist/docs/ScTableListMobile.md +282 -0
- package/dist/docs/ScTabs.md +268 -0
- package/dist/docs/ScTaxonomyPill.md +263 -0
- package/dist/docs/ScTextArea.md +259 -0
- package/dist/docs/ScTextField.md +324 -0
- package/dist/docs/ScThinkingStepIcon.md +249 -0
- package/dist/docs/ScTodoList.md +288 -0
- package/dist/docs/ScToggleSwitch.md +229 -0
- package/dist/docs/ScUsageHistoryMobile.md +194 -0
- package/dist/docs/ScVDivider.md +215 -0
- package/dist/docs/ScValueMappingL1.md +256 -0
- package/dist/docs/ScVersion.md +251 -0
- package/dist/docs/ScWorkspace.md +233 -0
- package/dist/docs/ScWorkspaceCard.md +234 -0
- package/dist/docs/ScWorkspaceSettingsMobile.md +265 -0
- package/dist/docs/ScWorkspaceSwitchCard.md +314 -0
- package/dist/docs/ScWorkspaceSwitchMobile.md +241 -0
- package/dist/docs/ScWorkspaceSwitchMobileV2.md +278 -0
- package/dist/docs/StreamoidSidebar.md +403 -0
- package/dist/docs/StreamoidWorkspaceSwitcher.md +307 -0
- package/dist/docs/UsageHistoryMobile.md +235 -0
- package/dist/docs/components.json +4849 -0
- package/dist/index.css +43 -37
- package/dist/index.d.mts +10 -0
- package/dist/index.d.ts +10 -0
- package/package.json +3 -2
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
---
|
|
2
|
+
component: ScPlanDetailsCard
|
|
3
|
+
package: "@streamoid/ui"
|
|
4
|
+
category: billing
|
|
5
|
+
status: stable
|
|
6
|
+
renders: div
|
|
7
|
+
tags: [current-plan, plan-summary, billing, subscription, active, badge, skeleton, loading, upgrade]
|
|
8
|
+
related: [ScPlanDetailsCardMobile, ScCreditsUsageCard, ScPlanCard, ScBadges, ScPairtext]
|
|
9
|
+
do_not_confuse_with: [ScPlanCard, ScPlanDetailsCardMobile, ScCreditsUsageCard, ScPlanComparison]
|
|
10
|
+
used_by: [cxo]
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# ScPlanDetailsCard
|
|
14
|
+
|
|
15
|
+
**The "this is the plan you're on" card at the top of the Billing page.** A
|
|
16
|
+
`Current plan` label with a billing icon, a green status badge, a divider, then
|
|
17
|
+
`Free · 30,000 credits` over `₹0.00 / month`, with a right-aligned CTA — plus a
|
|
18
|
+
built-in shimmer skeleton for while the subscription is still loading.
|
|
19
|
+
|
|
20
|
+
## TL;DR for agents
|
|
21
|
+
|
|
22
|
+
- **Reach for it when:** you need the single current-subscription summary strip,
|
|
23
|
+
usually side by side with `ScCreditsUsageCard`.
|
|
24
|
+
- **Don't reach for it when:** you're rendering a *buyable* plan tile
|
|
25
|
+
(→ `ScPlanCard`), the mobile billing screen (→ `ScPlanDetailsCardMobile`), or the
|
|
26
|
+
credits meter (→ `ScCreditsUsageCard`).
|
|
27
|
+
- **Four things that will bite you:**
|
|
28
|
+
1. `planPrice` must be the **whole** string including the period
|
|
29
|
+
(`"₹0.00 / month"`). `ScPlanCard.price` is the exact opposite — no period.
|
|
30
|
+
2. The badge is **always `variant="success"` (green)** and is pinned to a
|
|
31
|
+
**53px width**. `"Active"` fits; `"Past due"` and `"Cancelled"` render green
|
|
32
|
+
and overflow that fixed width (`ScBadges` sets no `overflow: hidden` and no
|
|
33
|
+
`nowrap`, so the label wraps and the pill grows taller).
|
|
34
|
+
3. `isLoading` replaces the badge, the text and the button with skeletons, so
|
|
35
|
+
`onUpgrade` is unreachable while loading.
|
|
36
|
+
4. Its CTA is a default-`variant`/`type` `ScButton`, which paints a
|
|
37
|
+
`Math.random()` canvas noise texture — non-deterministic in snapshots, blank
|
|
38
|
+
in SSR.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 1. How to use it
|
|
43
|
+
|
|
44
|
+
### Import
|
|
45
|
+
|
|
46
|
+
```tsx
|
|
47
|
+
import { ScPlanDetailsCard } from "@streamoid/ui";
|
|
48
|
+
import "@streamoid/ui/dist/index.css"; // once, at your app root
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Minimal usage
|
|
52
|
+
|
|
53
|
+
```tsx
|
|
54
|
+
<ScPlanDetailsCard
|
|
55
|
+
planName="Pro"
|
|
56
|
+
planCredits="30,000 credits"
|
|
57
|
+
planPrice="₹4,999.00 / month"
|
|
58
|
+
upgradeButtonText="Manage Plan"
|
|
59
|
+
onUpgrade={() => setShowPlans(true)}
|
|
60
|
+
/>
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Props
|
|
64
|
+
|
|
65
|
+
| Prop | Type | Default | Notes |
|
|
66
|
+
|---|---|---|---|
|
|
67
|
+
| `planName` | `string` | `"Free"` | ⚠️ Real default. Left half of the dotted name row. |
|
|
68
|
+
| `planCredits` | `string` | `"30,000 credits"` | ⚠️ Real default. Right half of the dotted row. Pre-formatted by you. |
|
|
69
|
+
| `planPrice` | `string` | `"₹0.00 / month"` | ⚠️ Real default. Rendered verbatim — **include the period yourself**. |
|
|
70
|
+
| `badgeText` | `string` | `"Active"` | ⚠️ Real default. Badge label. Colour is fixed to success — see Gotcha 2. |
|
|
71
|
+
| `badgeSubText` | `string` | – | Optional muted text after a dot separator, e.g. `"Downgrades on 12 Aug"`. `nowrap`. |
|
|
72
|
+
| `currentPlanLabel` | `string` | `"Current plan"` | ⚠️ Real default. Header text beside the billing icon. |
|
|
73
|
+
| `upgradeButtonText` | `string` | `"Upgrade"` | ⚠️ Real default. CTA label. |
|
|
74
|
+
| `isLoading` | `boolean` | `false` | Swaps badge / name row / price / button for shimmer pills. |
|
|
75
|
+
| `onUpgrade` | `() => void` | – | CTA click. Not reachable while `isLoading`. |
|
|
76
|
+
| `className` | `string` | – | Appended to the root class. |
|
|
77
|
+
| `...props` | `HTMLAttributes<HTMLDivElement>` | – | Spread onto the root div (`style`, `onClick`, `data-*`, `aria-*`). |
|
|
78
|
+
|
|
79
|
+
### What renders in each state
|
|
80
|
+
|
|
81
|
+
| Region | `isLoading={false}` | `isLoading={true}` |
|
|
82
|
+
|---|---|---|
|
|
83
|
+
| Header | billing icon + `currentPlanLabel` | same (never skeletonised) |
|
|
84
|
+
| Badge area | `ScBadges` + optional dot + `badgeSubText` | one 53×28 shimmer pill |
|
|
85
|
+
| Name row | `planName` · dot · `planCredits` | two shimmer pills, `aria-label="Loading plan details"` |
|
|
86
|
+
| Price | `planPrice` | one shimmer pill |
|
|
87
|
+
| CTA | `ScButton` (`size="md"`) | one 120×40 shimmer pill |
|
|
88
|
+
|
|
89
|
+
### Recipes
|
|
90
|
+
|
|
91
|
+
```tsx
|
|
92
|
+
// Live plan + a scheduled-downgrade note, loading-aware (the real CXO idiom)
|
|
93
|
+
<ScPlanDetailsCard
|
|
94
|
+
planName={planName}
|
|
95
|
+
planCredits={planCreditsText} // "30,000 credits"
|
|
96
|
+
planPrice={planAmount} // "₹4,999.00 / month"
|
|
97
|
+
badgeText="Active"
|
|
98
|
+
badgeSubText={scheduledDowngradeText} // undefined ⇒ dot + text omitted
|
|
99
|
+
currentPlanLabel="Current plan"
|
|
100
|
+
upgradeButtonText={downgradeScheduled ? "Cancel downgrade" : "Manage Plan"}
|
|
101
|
+
isLoading={isPlanDetailsLoading}
|
|
102
|
+
className="flex-1 min-w-0"
|
|
103
|
+
onUpgrade={handlePrimaryAction}
|
|
104
|
+
/>
|
|
105
|
+
|
|
106
|
+
// Side by side with the credits meter — both must be flex-1 min-w-0 or the
|
|
107
|
+
// nowrap text inside will blow the row out
|
|
108
|
+
<div className="flex items-start w-full" style={{ gap: "var(--spacing-6xl)" }}>
|
|
109
|
+
<ScPlanDetailsCard className="flex-1 min-w-0" {...plan} />
|
|
110
|
+
<ScCreditsUsageCard className="flex-1 min-w-0" {...credits} />
|
|
111
|
+
</div>
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## 2. Where to use it
|
|
117
|
+
|
|
118
|
+
- **Top-left card of the Billing overview**, paired with `ScCreditsUsageCard` in a
|
|
119
|
+
two-column row. One per page.
|
|
120
|
+
- Rendered from the shared **`@streamoid/settings`** billing page
|
|
121
|
+
(`packages/settings/src/billing-content.tsx`), which **CXO** mounts via
|
|
122
|
+
`src/app/components/settings-content.tsx`.
|
|
123
|
+
- This card does not adapt on its own — `.planInfo` is a fixed 2.875rem tall and its
|
|
124
|
+
text is `nowrap`. Below `md` you are expected to swap to
|
|
125
|
+
`ScPlanDetailsCardMobile`. Note that the shared settings billing page has **no
|
|
126
|
+
mobile branch** today: the only wiring of the mobile twin is CXO's
|
|
127
|
+
`src/app/components/mobile-billing-content.tsx:161`, reached from CXO's orphaned
|
|
128
|
+
local `billing-content.tsx`. Treat mobile billing as unwired until that moves
|
|
129
|
+
into `@streamoid/settings`.
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## 3. When to use it
|
|
134
|
+
|
|
135
|
+
### Use it when
|
|
136
|
+
|
|
137
|
+
- You need to state the **one** subscription currently in force, with a status
|
|
138
|
+
badge and a single primary action ("Manage Plan" / "Cancel downgrade").
|
|
139
|
+
- The data arrives async and you want the shimmer skeleton for free.
|
|
140
|
+
|
|
141
|
+
### Don't use it — reach for this instead
|
|
142
|
+
|
|
143
|
+
| Situation | Use instead |
|
|
144
|
+
|---|---|
|
|
145
|
+
| A plan the user could switch to, with a price and an Upgrade CTA | `ScPlanCard` |
|
|
146
|
+
| Mobile/narrow billing screen | `ScPlanDetailsCardMobile` |
|
|
147
|
+
| Credits remaining / progress meter | `ScCreditsUsageCard` |
|
|
148
|
+
| Feature comparison between plans | `ScPlanComparison` |
|
|
149
|
+
| A generic titled card with a slot | `ScDefaultCard` |
|
|
150
|
+
| A status pill on its own | `ScBadges` |
|
|
151
|
+
| A non-success status ("Past due", "Cancelled") | Nothing here fits — the badge is hardcoded green. Render your own `ScBadges` above the card, or fix the DS first. |
|
|
152
|
+
|
|
153
|
+
### Don't confuse with
|
|
154
|
+
|
|
155
|
+
| You may actually want | Not this |
|
|
156
|
+
|---|---|
|
|
157
|
+
| `ScPlanCard` — a buyable tile, price parsed, gradient Pro border | This is the read-only current-plan strip |
|
|
158
|
+
| `ScPlanDetailsCardMobile` — an identical prop list on a narrow, stacked layout | Not a responsive mode of this card; it is a separate export you must switch to yourself |
|
|
159
|
+
| `ScCreditsUsageCard` — same visual shell, same `ScPairtext` header, but a progress bar and a "Buy credits" CTA | Easy to mix up in a diff: both are 1.5rem-padded bordered cards with a header row and a divider |
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## 4. Why to use it
|
|
164
|
+
|
|
165
|
+
- **The skeleton is already correct.** Five shimmer pills at the exact widths of
|
|
166
|
+
the real content, so the card doesn't reflow when data lands — a common source
|
|
167
|
+
of layout jank on billing pages.
|
|
168
|
+
- **The dotted `name · credits` row** uses a `::after` pseudo-dot in a 24px box,
|
|
169
|
+
matching the same separator used in the badge row and in the mobile twin.
|
|
170
|
+
- **Composed from DS parts** (`ScPairtext`, `ScBadges`, `ScHDivider`, `ScButton`),
|
|
171
|
+
so icon sizing, badge radius, divider colour and button height all track the
|
|
172
|
+
tokens rather than local guesses.
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## Gotchas
|
|
177
|
+
|
|
178
|
+
**1. `planPrice` includes the period; `ScPlanCard.price` must not.** The two
|
|
179
|
+
sibling cards take opposite conventions.
|
|
180
|
+
|
|
181
|
+
```tsx
|
|
182
|
+
// RIGHT here
|
|
183
|
+
<ScPlanDetailsCard planPrice="₹4,999.00 / month" />
|
|
184
|
+
// RIGHT there
|
|
185
|
+
<ScPlanCard price="₹4,999.00" /> // card appends "/ month"
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
**2. The badge is green and 53px wide, always.** `variant="success"` is hardcoded
|
|
189
|
+
in the JSX and `.scBadgesInstance` sets `width: 3.3125rem !important`. `ScBadges`
|
|
190
|
+
has no `overflow: hidden` and no `white-space: nowrap`, so anything longer than
|
|
191
|
+
`"Active"` wraps inside that 53px box and makes the pill taller than the 28px
|
|
192
|
+
skeleton it replaces; nothing you pass makes it red or amber.
|
|
193
|
+
Use `badgeSubText` for the nuance ("Downgrades on 12 Aug") instead of trying to
|
|
194
|
+
recolour the badge.
|
|
195
|
+
|
|
196
|
+
**3. `isLoading` hides the CTA.** The button is replaced by a skeleton, so guard
|
|
197
|
+
against users being unable to act if a fetch hangs.
|
|
198
|
+
|
|
199
|
+
**4. Long text does not truncate — it overflows.** `.planName` is
|
|
200
|
+
`white-space: nowrap` with no `overflow: hidden`, and `.planInfo` is a fixed
|
|
201
|
+
2.875rem tall. Give the card `min-width: 0` and keep `planCredits` short.
|
|
202
|
+
|
|
203
|
+
**5. You cannot add or change the CTA icon.** The JSX passes
|
|
204
|
+
`icon={<SiconHome />}` to `ScButton` without a `styleVariant`, so `ScButton`
|
|
205
|
+
renders label-only and the icon is dead code. There is no icon prop.
|
|
206
|
+
|
|
207
|
+
**6. The CTA is a `primary`/`primary` `ScButton`.** That combination generates a
|
|
208
|
+
canvas noise texture with `Math.random()` and needs a DOM — expect snapshot churn
|
|
209
|
+
and nothing painted during SSR. (See `SC-Button/README.md` Gotcha 7.)
|
|
210
|
+
|
|
211
|
+
**7. Missing `className` leaks the string `"undefined"` into the class list.** The
|
|
212
|
+
root is `styles.scPlanDetailsCard + " " + className`. Harmless visually, but it
|
|
213
|
+
shows up in DOM snapshots and breaks naive `class="…"` equality assertions.
|
|
214
|
+
|
|
215
|
+
**8. `onUpgrade` is not the only click target.** Because `...props` is spread onto
|
|
216
|
+
the root, a stray `onClick` you pass fires for clicks anywhere in the card,
|
|
217
|
+
including the CTA.
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## In the wild
|
|
222
|
+
|
|
223
|
+
```tsx
|
|
224
|
+
// npm-components packages/settings/src/billing-content.tsx:2027
|
|
225
|
+
<ScPlanDetailsCard
|
|
226
|
+
planName={planName}
|
|
227
|
+
planCredits={planCreditsText}
|
|
228
|
+
planPrice={planAmount}
|
|
229
|
+
badgeText="Active"
|
|
230
|
+
badgeSubText={scheduledDowngradeText}
|
|
231
|
+
currentPlanLabel="Current plan"
|
|
232
|
+
upgradeButtonText={subscription?.downgradeScheduled ? "Cancel downgrade" : "Manage Plan"}
|
|
233
|
+
isLoading={isPlanDetailsLoading}
|
|
234
|
+
className="flex-1 min-w-0"
|
|
235
|
+
onUpgrade={() => { /* log + open plans, or cancel the downgrade */ }}
|
|
236
|
+
/>
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## Related
|
|
242
|
+
|
|
243
|
+
- `ScPlanDetailsCardMobile` — the mobile twin, same prop names.
|
|
244
|
+
- `ScCreditsUsageCard` — the card that sits next to it.
|
|
245
|
+
- `ScPlanCard` — the buyable tiles the CTA navigates to.
|
|
246
|
+
- `ScBadges` / `ScPairtext` / `ScHDivider` / `ScButton` — the parts it composes.
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
---
|
|
2
|
+
component: ScPlanDetailsCardMobile
|
|
3
|
+
package: "@streamoid/ui"
|
|
4
|
+
category: mobile
|
|
5
|
+
status: stable
|
|
6
|
+
renders: div
|
|
7
|
+
tags: [mobile, billing, plan, current-plan, upgrade, skeleton, loading, card, cxo]
|
|
8
|
+
related: [ScPlanDetailsCard, ScCreditsUsageCardMobile, ScPlanCard, ScBadges, ScButton]
|
|
9
|
+
do_not_confuse_with: [ScPlanDetailsCard, ScPlanCard, ScPlanComparison, ScCreditsUsageCardMobile]
|
|
10
|
+
used_by: [cxo]
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# ScPlanDetailsCardMobile
|
|
14
|
+
|
|
15
|
+
**The current-plan summary on CXO's mobile billing screen.** A bordered full-width
|
|
16
|
+
card: billing icon + "Current plan" label with a green `ScBadges` status on the
|
|
17
|
+
right, a divider, `planName · planCredits` with the price under it, and a
|
|
18
|
+
full-width **blue-gradient** Upgrade button. Has a built-in shimmer skeleton state.
|
|
19
|
+
|
|
20
|
+
## TL;DR for agents
|
|
21
|
+
|
|
22
|
+
- **Reach for it when:** the mobile billing screen needs the "what plan am I on"
|
|
23
|
+
block at the top.
|
|
24
|
+
- **Don't reach for it when:** you're on desktop (→ `ScPlanDetailsCard`, identical
|
|
25
|
+
prop surface), you're rendering *purchasable* plans (→ `ScPlanCard`), or you want
|
|
26
|
+
a feature-by-plan grid (→ `ScPlanComparison`).
|
|
27
|
+
- **Five things that will bite you:**
|
|
28
|
+
1. **The Upgrade button's gradient is a hardcoded inline `style`** — raw
|
|
29
|
+
`rgb()` blue, not tokens. It overrides `variant="primary"` and you cannot
|
|
30
|
+
change or theme it from outside.
|
|
31
|
+
2. **The badge is always `variant="success"`.** There is no way to show a red
|
|
32
|
+
"Past due" or amber "Trialing" — `badgeText` only changes the words.
|
|
33
|
+
3. **Every text prop has a demo default**, including `planPrice = "₹0.00 / month"`
|
|
34
|
+
— a rupee price on an app that bills in dollars.
|
|
35
|
+
4. `isLoading` replaces the badge, the plan lines **and the button** with
|
|
36
|
+
skeletons, so `onUpgrade` is unreachable while loading.
|
|
37
|
+
5. Its prop *types* are identical to the desktop `ScPlanDetailsCard` (only the
|
|
38
|
+
`planName` default differs: `"Pro"` here, `"Free"` there), which makes picking
|
|
39
|
+
the wrong one silent.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## 1. How to use it
|
|
44
|
+
|
|
45
|
+
### Import
|
|
46
|
+
|
|
47
|
+
```tsx
|
|
48
|
+
import { ScPlanDetailsCardMobile } from "@streamoid/ui";
|
|
49
|
+
import "@streamoid/ui/dist/index.css"; // once, at your app root
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Minimal usage
|
|
53
|
+
|
|
54
|
+
```tsx
|
|
55
|
+
<ScPlanDetailsCardMobile
|
|
56
|
+
planName={plan.name}
|
|
57
|
+
planCredits={`${plan.credits.toLocaleString()} credits`}
|
|
58
|
+
planPrice={`$${plan.price} / month`}
|
|
59
|
+
badgeText="Active"
|
|
60
|
+
onUpgrade={openUpgrade}
|
|
61
|
+
/>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Props
|
|
65
|
+
|
|
66
|
+
| Prop | Type | Default | Notes |
|
|
67
|
+
|---|---|---|---|
|
|
68
|
+
| `planName` | `string` | `"Pro"` | ⚠️ Demo default. First half of the `name · credits` line. |
|
|
69
|
+
| `planCredits` | `string` | `"30,000 credits"` | ⚠️ Demo default. Second half, after a dot separator. You append the word "credits". |
|
|
70
|
+
| `planPrice` | `string` | `"₹0.00 / month"` | ⚠️ Demo default **in rupees**. Grey sub-line. You format currency and period. |
|
|
71
|
+
| `badgeText` | `string` | `"Active"` | ⚠️ Text of the badge. The badge is hardwired to `variant="success"` / `styleVariant="opaque"`. |
|
|
72
|
+
| `badgeSubText` | `string` | – | Optional extra grey text after the badge, preceded by a 4px dot. Renders only when truthy. |
|
|
73
|
+
| `currentPlanLabel` | `string` | `"Current plan"` | ⚠️ Header label beside the billing icon. |
|
|
74
|
+
| `upgradeButtonText` | `string` | `"Upgrade"` | ⚠️ CTA label. |
|
|
75
|
+
| `isLoading` | `boolean` | `false` | Swaps badge, plan lines and button for shimmer skeletons. See the state table. |
|
|
76
|
+
| `onUpgrade` | `() => void` | – | The CTA's `onClick`. Unreachable while `isLoading`. |
|
|
77
|
+
| `className` | `string` | – | Appended after internal classes (safely — uses `className ?? ""`). |
|
|
78
|
+
| `...props` | `React.HTMLAttributes<HTMLDivElement>` | – | Spread onto the card root, **not** the button. |
|
|
79
|
+
|
|
80
|
+
### What renders in each state
|
|
81
|
+
|
|
82
|
+
| Region | `isLoading={false}` | `isLoading={true}` |
|
|
83
|
+
|---|---|---|
|
|
84
|
+
| Header left | `SiconBilling` + `currentPlanLabel` | unchanged — always visible |
|
|
85
|
+
| Header right | `ScBadges` (success/opaque) + optional dot + `badgeSubText` | one 53×28 shimmer pill |
|
|
86
|
+
| Plan info | `planName` · `planCredits`, then `planPrice` | two inline pills (`aria-label="Loading plan details"`) + a price pill |
|
|
87
|
+
| Action | gradient `ScButton` with `upgradeButtonText` | one full-width 40px shimmer pill |
|
|
88
|
+
|
|
89
|
+
### Recipes
|
|
90
|
+
|
|
91
|
+
```tsx
|
|
92
|
+
// Real load-then-show, the CXO shape
|
|
93
|
+
<ScPlanDetailsCardMobile
|
|
94
|
+
isLoading={!plan}
|
|
95
|
+
planName={plan?.name ?? ""}
|
|
96
|
+
planCredits={plan ? `${plan.credits.toLocaleString("en-US")} credits` : ""}
|
|
97
|
+
planPrice={plan ? `$${plan.amount.toFixed(2)} / month` : ""}
|
|
98
|
+
badgeText={plan?.status === "active" ? "Active" : "Inactive"}
|
|
99
|
+
onUpgrade={() => setShowPlans(true)}
|
|
100
|
+
/>
|
|
101
|
+
|
|
102
|
+
// Add a renewal note after the badge
|
|
103
|
+
<ScPlanDetailsCardMobile
|
|
104
|
+
planName="Pro"
|
|
105
|
+
planCredits="30,000 credits"
|
|
106
|
+
planPrice="$49.00 / month"
|
|
107
|
+
badgeText="Active"
|
|
108
|
+
badgeSubText="Renews Aug 12"
|
|
109
|
+
onUpgrade={openUpgrade}
|
|
110
|
+
/>
|
|
111
|
+
|
|
112
|
+
// You want a non-green status? The badge can't do it — render your own beside the card.
|
|
113
|
+
// (badgeText="Past due" still renders GREEN.)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## 2. Where to use it
|
|
119
|
+
|
|
120
|
+
- **CXO mobile billing screen**, the first block on the page, directly above
|
|
121
|
+
`ScCreditsUsageCardMobile` and the invoice/usage `ScTabSwitcher`.
|
|
122
|
+
- Any narrow single-column surface that needs a "your current subscription" summary
|
|
123
|
+
with one upgrade path.
|
|
124
|
+
|
|
125
|
+
It composes `SiconBilling`, one `ScBadges` and one `ScButton` internally. Don't nest
|
|
126
|
+
your own badge or button — use `badgeText` / `upgradeButtonText`.
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## 3. When to use it
|
|
131
|
+
|
|
132
|
+
### Use it when
|
|
133
|
+
|
|
134
|
+
- The viewport is the mobile breakpoint and the card must be full-width.
|
|
135
|
+
- The plan is a **fact to display**, with exactly one forward action (Upgrade).
|
|
136
|
+
- You want a skeleton state for free while the subscription request is in flight.
|
|
137
|
+
|
|
138
|
+
### Don't use it — reach for this instead
|
|
139
|
+
|
|
140
|
+
| Situation | Use instead |
|
|
141
|
+
|---|---|
|
|
142
|
+
| Desktop billing page | `ScPlanDetailsCard` — same props, desktop metrics |
|
|
143
|
+
| A tile in a "choose a plan" grid (price, features, CTA) | `ScPlanCard` |
|
|
144
|
+
| Feature-by-plan comparison table | `ScPlanComparison` |
|
|
145
|
+
| Credits remaining / buy credits | `ScCreditsUsageCardMobile` |
|
|
146
|
+
| A status chip on its own, any colour | `ScBadges` directly |
|
|
147
|
+
| Non-green plan status (past due, canceled) | `ScBadges` beside a plain card — this component can't recolour its badge |
|
|
148
|
+
|
|
149
|
+
### Don't confuse with
|
|
150
|
+
|
|
151
|
+
| You may actually want | Not this |
|
|
152
|
+
|---|---|
|
|
153
|
+
| `ScPlanDetailsCard` — the desktop twin with an **identical** prop list | Nothing in the types tells you which one you imported; check the `Mobile` suffix |
|
|
154
|
+
| `ScPlanCard` — a purchasable plan tile (formatted price, feature list) | This card describes the plan you already have |
|
|
155
|
+
| `ScCreditsUsageCardMobile` — same chrome, one slot lower on the screen | Credits, not plan; secondary button, not gradient |
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## 4. Why to use it
|
|
160
|
+
|
|
161
|
+
- **The skeleton is already built.** Five separately-sized shimmer pills with a
|
|
162
|
+
shared 1.1s `skeletonShimmer` keyframe, and an `aria-label` on the plan row.
|
|
163
|
+
Hand-rolling that is where mobile billing screens usually look cheap.
|
|
164
|
+
- **Prop-identical to the desktop card**, so a responsive screen can pick the
|
|
165
|
+
component at the breakpoint and pass the same view-model object to both.
|
|
166
|
+
- **Card chrome is shared with `ScCreditsUsageCardMobile`** — `--radius-3xl`, 1px
|
|
167
|
+
`--alias-border-subtle`, `backdrop-filter: blur(4px)`, 16px padding — so the two
|
|
168
|
+
stacked cards line up exactly.
|
|
169
|
+
- **Correct token usage** (`--alias-text-and-icons-*`, `--alias-surface-base`), so
|
|
170
|
+
the card body genuinely flips light/dark — the gradient button is the one
|
|
171
|
+
exception (see Gotcha 1).
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## Gotchas
|
|
176
|
+
|
|
177
|
+
**1. The Upgrade button's colour is an inline style you cannot reach.** The
|
|
178
|
+
component renders `variant="primary"` *and then* overrides its background with a
|
|
179
|
+
literal gradient:
|
|
180
|
+
|
|
181
|
+
```tsx
|
|
182
|
+
style={{ backgroundImage: "linear-gradient(154deg, rgb(18, 57, 255) 0%, rgb(73, 206, 255) 100%)" }}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Raw `rgb()`, no tokens, so it is the same blue in light and dark mode, and
|
|
186
|
+
`className` on the card can't win against an inline style on the button. If the
|
|
187
|
+
brand blue must change, change the DS.
|
|
188
|
+
|
|
189
|
+
**2. The badge is always green.** `variant="success"` is hardcoded.
|
|
190
|
+
|
|
191
|
+
```tsx
|
|
192
|
+
// MISLEADING — renders "Past due" in success green
|
|
193
|
+
<ScPlanDetailsCardMobile badgeText="Past due" />
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
**3. Demo defaults everywhere, and the price default is in rupees.** Rendering the
|
|
197
|
+
card bare gives you `Pro · 30,000 credits` / `₹0.00 / month` / `Active`, which looks
|
|
198
|
+
like real data in a screenshot.
|
|
199
|
+
|
|
200
|
+
**4. `isLoading` hides the CTA.** While loading there is no button at all, so
|
|
201
|
+
`onUpgrade` cannot fire. Don't rely on the button existing for focus management.
|
|
202
|
+
|
|
203
|
+
**5. `planCredits` is not a number.** You append the word "credits" (and do the
|
|
204
|
+
locale grouping). The card only inserts the dot separator.
|
|
205
|
+
|
|
206
|
+
**6. `badgeSubText` is dropped when falsy.** Empty string means "no dot, no text" —
|
|
207
|
+
which is usually what you want, but means you can't render a deliberate blank.
|
|
208
|
+
|
|
209
|
+
**7. `...props` lands on the card root.** `onClick` makes the *whole card*
|
|
210
|
+
clickable in addition to the Upgrade button; `style` restyles the card, never the
|
|
211
|
+
button.
|
|
212
|
+
|
|
213
|
+
**8. `backdrop-filter: blur(4px)` creates a containing block,** so any
|
|
214
|
+
`position: fixed` descendant anchors to this card rather than the viewport.
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## In the wild
|
|
219
|
+
|
|
220
|
+
```tsx
|
|
221
|
+
// cxo-dashboard src/app/components/mobile-billing-content.tsx:161
|
|
222
|
+
<ScPlanDetailsCardMobile
|
|
223
|
+
planName={planName}
|
|
224
|
+
planCredits={planCredits}
|
|
225
|
+
planPrice={planPrice}
|
|
226
|
+
badgeText={badgeText}
|
|
227
|
+
onUpgrade={onUpgrade}
|
|
228
|
+
className="w-full"
|
|
229
|
+
/>
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## Related
|
|
235
|
+
|
|
236
|
+
- `ScPlanDetailsCard` — the desktop twin; identical props.
|
|
237
|
+
- `ScCreditsUsageCardMobile` — the credits card immediately below it.
|
|
238
|
+
- `ScPlanCard` / `ScPlanComparison` — the "choose a plan" surfaces.
|
|
239
|
+
- `ScBadges` — the status chip it renders; use directly if you need another colour.
|
|
240
|
+
- `ScButton` — the CTA, here with its background overridden.
|