@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,224 @@
|
|
|
1
|
+
---
|
|
2
|
+
component: ScCreditsUsageCardMobile
|
|
3
|
+
package: "@streamoid/ui"
|
|
4
|
+
category: mobile
|
|
5
|
+
status: stable
|
|
6
|
+
renders: div
|
|
7
|
+
tags: [mobile, billing, credits, usage, meter, buy-credits, card, cxo]
|
|
8
|
+
related: [ScCreditsUsageCard, ScPlanDetailsCardMobile, ScButton, CreditWarningBanner]
|
|
9
|
+
do_not_confuse_with: [ScCreditsUsageCard, ScPlanDetailsCardMobile, CreditWarningBanner]
|
|
10
|
+
used_by: [cxo]
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# ScCreditsUsageCardMobile
|
|
14
|
+
|
|
15
|
+
**The credits-remaining block on CXO's mobile billing screen.** A bordered
|
|
16
|
+
full-width card: credits icon + "Credits usage" label, a divider, the
|
|
17
|
+
`used / total` figure with a "remaining" sub-line, and a full-width
|
|
18
|
+
**secondary** `ScButton` for buying credits.
|
|
19
|
+
|
|
20
|
+
## TL;DR for agents
|
|
21
|
+
|
|
22
|
+
- **Reach for it when:** you are laying out the mobile (narrow, single-column)
|
|
23
|
+
billing screen and need the credits meter above the invoice/usage tabs.
|
|
24
|
+
- **Don't reach for it when:** you're on desktop (→ `ScCreditsUsageCard`, which
|
|
25
|
+
additionally has a `progress` bar and a disable-able buy button), or you want a
|
|
26
|
+
low-credits *alert* rather than a summary (→ `CreditWarningBanner`).
|
|
27
|
+
- **Four things that will bite you:**
|
|
28
|
+
1. **Every text prop has a real demo default.** Render it bare and you ship
|
|
29
|
+
`"8,450 / 30,000"` and `"21,550 (60%) Remaining"`.
|
|
30
|
+
2. **There is no progress bar.** The desktop card's `progress` prop does not
|
|
31
|
+
exist here — the percentage lives inside the `remainingText` string you build.
|
|
32
|
+
3. **There is no way to disable the buy button.** The desktop card's
|
|
33
|
+
`buyButtonState` is absent; omit `onBuyClick` and the button still looks live.
|
|
34
|
+
4. The card is already `width: 100%`; `usageText`/`remainingText` are opaque
|
|
35
|
+
strings — the card does no formatting, no maths, no locale handling.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## 1. How to use it
|
|
40
|
+
|
|
41
|
+
### Import
|
|
42
|
+
|
|
43
|
+
```tsx
|
|
44
|
+
import { ScCreditsUsageCardMobile } from "@streamoid/ui";
|
|
45
|
+
import "@streamoid/ui/dist/index.css"; // once, at your app root
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Minimal usage
|
|
49
|
+
|
|
50
|
+
```tsx
|
|
51
|
+
<ScCreditsUsageCardMobile
|
|
52
|
+
usageText={`${used.toLocaleString()} / ${total.toLocaleString()}`}
|
|
53
|
+
remainingText={`${remaining.toLocaleString()} (${pct}%) Remaining`}
|
|
54
|
+
onBuyClick={openBuyCredits}
|
|
55
|
+
/>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Props
|
|
59
|
+
|
|
60
|
+
| Prop | Type | Default | Notes |
|
|
61
|
+
|---|---|---|---|
|
|
62
|
+
| `usageLabel` | `string` | `"Credits usage"` | ⚠️ Header label beside the credits icon. Hardcoded English default. |
|
|
63
|
+
| `usageText` | `string` | `"8,450 / 30,000"` | ⚠️ Demo default. The big `used / total` line. You build the whole string. |
|
|
64
|
+
| `remainingText` | `string` | `"21,550 (60%) Remaining"` | ⚠️ Demo default. The grey sub-line. Includes the percentage — the card computes nothing. |
|
|
65
|
+
| `buyButtonText` | `string` | `"Buy credits"` | ⚠️ Hardcoded English default. |
|
|
66
|
+
| `onBuyClick` | `() => void` | – | Wired to the internal `ScButton`'s `onClick`. |
|
|
67
|
+
| `className` | `string` | – | Appended after internal classes (safely — this card uses `className ?? ""`). |
|
|
68
|
+
| `...props` | `React.HTMLAttributes<HTMLDivElement>` | – | Spread onto the card root. `style`, `data-*`, `onClick` land on the **card**, not the button. |
|
|
69
|
+
|
|
70
|
+
### What the card renders, top to bottom
|
|
71
|
+
|
|
72
|
+
| Region | Content | Configurable? |
|
|
73
|
+
|---|---|---|
|
|
74
|
+
| Header | `SiconCredits` (24×24, tertiary token) + `usageLabel` | label only — the icon is fixed |
|
|
75
|
+
| Divider | 0.5px `--alias-border-divider` | no |
|
|
76
|
+
| Usage | `usageText` (18px/500 primary) then `remainingText` (14px/500 tertiary) | text only |
|
|
77
|
+
| Action | `ScButton variant="secondary" size="md"`, forced to `width: 100% !important` | `buyButtonText`, `onBuyClick` |
|
|
78
|
+
|
|
79
|
+
### Recipes
|
|
80
|
+
|
|
81
|
+
```tsx
|
|
82
|
+
// The CXO idiom: caller owns all formatting
|
|
83
|
+
const pct = Math.round((remaining / total) * 100);
|
|
84
|
+
|
|
85
|
+
<ScCreditsUsageCardMobile
|
|
86
|
+
usageLabel="Credits usage"
|
|
87
|
+
usageText={`${used.toLocaleString("en-US")} / ${total.toLocaleString("en-US")}`}
|
|
88
|
+
remainingText={`${remaining.toLocaleString("en-US")} (${pct}%) Remaining`}
|
|
89
|
+
buyButtonText="Buy credits"
|
|
90
|
+
onBuyClick={() => setShowBuyCredits(true)}
|
|
91
|
+
/>
|
|
92
|
+
|
|
93
|
+
// Loading — this card has NO isLoading prop (unlike ScPlanDetailsCardMobile).
|
|
94
|
+
// Either render your own skeleton, or pass placeholder strings:
|
|
95
|
+
<ScCreditsUsageCardMobile usageText="—" remainingText="Loading…" onBuyClick={undefined} />
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## 2. Where to use it
|
|
101
|
+
|
|
102
|
+
- **CXO mobile billing screen**, stacked directly under `ScPlanDetailsCardMobile`
|
|
103
|
+
and above the `ScTabSwitcher` that toggles Invoice history / Usage history.
|
|
104
|
+
- Any narrow single-column surface (mobile drawer, bottom sheet) that needs a
|
|
105
|
+
credits summary with a single CTA.
|
|
106
|
+
|
|
107
|
+
It composes `SiconCredits` and one `ScButton` internally. Do **not** nest your own
|
|
108
|
+
button — pass `buyButtonText` / `onBuyClick`.
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## 3. When to use it
|
|
113
|
+
|
|
114
|
+
### Use it when
|
|
115
|
+
|
|
116
|
+
- The viewport is the mobile breakpoint and the card must be full-width.
|
|
117
|
+
- A single "Buy credits" action is the only affordance you need.
|
|
118
|
+
- You already have the numbers formatted as display strings.
|
|
119
|
+
|
|
120
|
+
### Don't use it — reach for this instead
|
|
121
|
+
|
|
122
|
+
| Situation | Use instead |
|
|
123
|
+
|---|---|
|
|
124
|
+
| Desktop billing page | `ScCreditsUsageCard` — same prop names **plus** `progress`, `buyButtonState`, `buyButtonHoverText` |
|
|
125
|
+
| You need a visual usage bar | `ScCreditsUsageCard` (has `progress`), or compose `ScProgressBar` yourself |
|
|
126
|
+
| Low-credits warning / nudge in a sidebar | `CreditWarningBanner` |
|
|
127
|
+
| Current-plan summary (name, price, Upgrade) | `ScPlanDetailsCardMobile` |
|
|
128
|
+
| A plan tile in a pricing grid | `ScPlanCard` |
|
|
129
|
+
| A row of the usage-log list | `UsageHistoryMobile` |
|
|
130
|
+
|
|
131
|
+
### Don't confuse with
|
|
132
|
+
|
|
133
|
+
| You may actually want | Not this |
|
|
134
|
+
|---|---|
|
|
135
|
+
| `ScCreditsUsageCard` — the desktop twin, with a progress bar and a disable-able button | This mobile twin has neither |
|
|
136
|
+
| `CreditWarningBanner` — takes numbers (`availableCredits`, `remainingPct`) and decides its own tone | This card takes pre-built strings and never changes colour |
|
|
137
|
+
| `ScPlanDetailsCardMobile` — visually near-identical card, one slot down the screen | Different content and a *gradient* button |
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## 4. Why to use it
|
|
142
|
+
|
|
143
|
+
- **Matches its desktop twin's anatomy prop-for-prop** (`usageLabel`,
|
|
144
|
+
`usageText`, `remainingText`, `buyButtonText`, `onBuyClick`), so a responsive
|
|
145
|
+
screen can swap components at the breakpoint without reshaping its data.
|
|
146
|
+
- **Correct token usage.** Unlike most of the `*Mobile` family, this card uses the
|
|
147
|
+
real `--alias-text-and-icons-*` names, so it genuinely flips between dark and
|
|
148
|
+
light themes.
|
|
149
|
+
- **The CTA is a real `ScButton`**, so it inherits the shared button shape, focus
|
|
150
|
+
behaviour and theme flip — the `width: 100% !important` override is the only
|
|
151
|
+
mobile-specific bit, and it's already done for you.
|
|
152
|
+
- **One place to change** the card chrome (radius `--radius-3xl`, 1px
|
|
153
|
+
`--alias-border-subtle`, `backdrop-filter: blur(4px)`) shared with
|
|
154
|
+
`ScPlanDetailsCardMobile`.
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## Gotchas
|
|
159
|
+
|
|
160
|
+
**1. All four text props have shipping-quality demo defaults.** There is no
|
|
161
|
+
"empty" state — forget a prop and you ship believable wrong numbers.
|
|
162
|
+
|
|
163
|
+
```tsx
|
|
164
|
+
// WRONG — renders "Credits usage / 8,450 / 30,000 / 21,550 (60%) Remaining"
|
|
165
|
+
<ScCreditsUsageCardMobile onBuyClick={buy} />
|
|
166
|
+
|
|
167
|
+
// RIGHT
|
|
168
|
+
<ScCreditsUsageCardMobile
|
|
169
|
+
usageText={`${used} / ${total}`}
|
|
170
|
+
remainingText={`${remaining} (${pct}%) Remaining`}
|
|
171
|
+
onBuyClick={buy}
|
|
172
|
+
/>
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
**2. No `progress` prop.** The desktop `ScCreditsUsageCard` draws a bar; this one
|
|
176
|
+
does not. The only percentage the user sees is the one you typed into
|
|
177
|
+
`remainingText`, so keep it consistent with `usageText` yourself.
|
|
178
|
+
|
|
179
|
+
**3. No `buyButtonState`.** You cannot disable the CTA through the card. If the
|
|
180
|
+
user must not buy (no permission, no payment method), don't render the card's
|
|
181
|
+
action path — conditionally render your own `ScButton` outside the card, or gate
|
|
182
|
+
inside `onBuyClick`.
|
|
183
|
+
|
|
184
|
+
**4. No `isLoading` / skeleton.** Its sibling `ScPlanDetailsCardMobile` *does*
|
|
185
|
+
have one. Passing `isLoading` here is a type error; render your own placeholder.
|
|
186
|
+
|
|
187
|
+
**5. `style` and `onClick` go to the card, not the button.** `...props` is spread
|
|
188
|
+
on the root `div`, so `onClick` makes the whole card clickable *in addition to*
|
|
189
|
+
the button. That is almost never what you want.
|
|
190
|
+
|
|
191
|
+
**6. `backdrop-filter: blur(4px)` on the root creates a containing block.** Any
|
|
192
|
+
`position: fixed` descendant (a portal-less popover, a sticky footer) will be
|
|
193
|
+
positioned against this card instead of the viewport.
|
|
194
|
+
|
|
195
|
+
**7. The header icon is not swappable.** `SiconCredits` is hardcoded, with its
|
|
196
|
+
colour pinned to `--alias-text-and-icons-tertiary`. There is no `icon` prop.
|
|
197
|
+
|
|
198
|
+
**8. `usageLabel` / `buyButtonText` are the only localisable strings.** Everything
|
|
199
|
+
else you supply, so a localised surface must format numbers and the word
|
|
200
|
+
"Remaining" itself.
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## In the wild
|
|
205
|
+
|
|
206
|
+
```tsx
|
|
207
|
+
// cxo-dashboard src/app/components/mobile-billing-content.tsx:171
|
|
208
|
+
<ScCreditsUsageCardMobile
|
|
209
|
+
usageText={usageText}
|
|
210
|
+
remainingText={remainingText}
|
|
211
|
+
onBuyClick={onBuyCredits}
|
|
212
|
+
className="w-full"
|
|
213
|
+
/>
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## Related
|
|
219
|
+
|
|
220
|
+
- `ScCreditsUsageCard` — the desktop twin; has `progress` and `buyButtonState`.
|
|
221
|
+
- `ScPlanDetailsCardMobile` — the card directly above it on the same screen.
|
|
222
|
+
- `CreditWarningBanner` — the alert form, driven by numbers not strings.
|
|
223
|
+
- `ScButton` — what the CTA actually is; `variant="secondary"`, `size="md"`.
|
|
224
|
+
- `UsageHistoryMobile` / `InvoiceHistoryMobile` — the list rows below the tabs.
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
---
|
|
2
|
+
component: ScDefaultCard
|
|
3
|
+
package: "@streamoid/ui"
|
|
4
|
+
category: cards
|
|
5
|
+
status: stable
|
|
6
|
+
renders: div
|
|
7
|
+
tags: [card, option, choice, picker, default, hover, title, description, centered, catalogix]
|
|
8
|
+
related: [ScMappingCard, ScStoreCard, ScAppListingCard, ScRadio, ScTabField, ScModal, ScDrawer]
|
|
9
|
+
do_not_confuse_with: [ScAppListingCard, ScStoreCard, ScMappingCard, ScBriefCard, ScRadio]
|
|
10
|
+
used_by: [catalogix]
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# ScDefaultCard
|
|
14
|
+
|
|
15
|
+
**The generic "pick this option" card.** A full-width bordered box with a centred
|
|
16
|
+
title and an optional smaller description underneath. Two visual states — default
|
|
17
|
+
and hover — and nothing else: no icon, no badge, no button, no state machine.
|
|
18
|
+
|
|
19
|
+
## TL;DR for agents
|
|
20
|
+
|
|
21
|
+
- **Reach for it when:** a screen asks "which of these routes do you want?" and each
|
|
22
|
+
route is a title plus a one-line cost/time hint — stacked vertically, often with
|
|
23
|
+
"or" separators between them.
|
|
24
|
+
- **Don't reach for it when:** the card needs an icon and lives in a grid
|
|
25
|
+
(→ `ScAppListingCard`), it carries a mapping lifecycle
|
|
26
|
+
(→ `ScMappingCard`), it's a store summary (→ `ScStoreCard`), or the choice is a
|
|
27
|
+
**form value you will save** (→ `ScRadio` / `ScTabField`).
|
|
28
|
+
- **Three things that will bite you:**
|
|
29
|
+
1. `title` defaults to `"Title"` and `description` to `"Description"` — forget
|
|
30
|
+
either and you ship placeholder copy.
|
|
31
|
+
2. `cursor: pointer` is baked in, but there is **no `role`, `tabIndex` or key
|
|
32
|
+
handling**. Every Catalogix call site hand-adds `role="button" tabIndex={0}`;
|
|
33
|
+
only the Products/taxonomy ones also add `onKeyDown` (ConnectOptions forgets
|
|
34
|
+
it — copy the Products version, not that one).
|
|
35
|
+
3. `state="hover"` force-renders the hover skin. It is for Figma parity /
|
|
36
|
+
screenshots, **not** for wiring your own mouse handlers — real `:hover`
|
|
37
|
+
already works.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## 1. How to use it
|
|
42
|
+
|
|
43
|
+
### Import
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
import { ScDefaultCard } from "@streamoid/ui";
|
|
47
|
+
import "@streamoid/ui/dist/index.css"; // once, at your app root
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Minimal usage
|
|
51
|
+
|
|
52
|
+
```tsx
|
|
53
|
+
<ScDefaultCard
|
|
54
|
+
title="Use Catalogix taxonomy"
|
|
55
|
+
description="Average Time : Instant."
|
|
56
|
+
role="button"
|
|
57
|
+
tabIndex={0}
|
|
58
|
+
onClick={choose}
|
|
59
|
+
/>
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Props
|
|
63
|
+
|
|
64
|
+
| Prop | Type | Default | Notes |
|
|
65
|
+
|---|---|---|---|
|
|
66
|
+
| `title` | `string` | `"Title"` | ⚠️ Real default. `text-md-regular`, primary, centred, `word-break: break-word`. |
|
|
67
|
+
| `description` | `string` | `"Description"` | ⚠️ Real default. `text-xs-regular`, tertiary, centred. Only rendered when `showDescription` is true **and** the string is non-empty. |
|
|
68
|
+
| `showDescription` | `boolean` | `true` | ⚠️ Defaults to **true**, so the description renders unless you opt out. `false` → title-only card. |
|
|
69
|
+
| `state` | `"default"` \| `"hover"` | `"default"` | Forces the visual state. `"hover"` applies the same skin as real `:hover`. |
|
|
70
|
+
| `className` | `string` | – | Appended after the internal classes, so it wins on equal specificity. |
|
|
71
|
+
| `...props` | `HTMLAttributes<HTMLDivElement>` | – | `onClick`, `role`, `tabIndex`, `onKeyDown`, `style`, `aria-*`, `data-*` all land on the root div. |
|
|
72
|
+
|
|
73
|
+
### What renders in each state
|
|
74
|
+
|
|
75
|
+
| Region | `state="default"` | `state="hover"` (or real `:hover`) |
|
|
76
|
+
|---|---|---|
|
|
77
|
+
| Background | `--alias-surface-base` | `--alias-surface-basesubtle` — ⚠️ **identical (`#ffffff`) in light mode** |
|
|
78
|
+
| Border | `--alias-border-subtle` | `--alias-border-default` — the only hover cue that survives light mode |
|
|
79
|
+
| Content | title (+ description if `showDescription && description`) | same |
|
|
80
|
+
|
|
81
|
+
### Recipes
|
|
82
|
+
|
|
83
|
+
```tsx
|
|
84
|
+
// The Catalogix idiom: a stack of routes with "or" separators, fully accessible
|
|
85
|
+
{OPTIONS.map((option, idx) => (
|
|
86
|
+
<Fragment key={option.key}>
|
|
87
|
+
<ScDefaultCard
|
|
88
|
+
title={option.title}
|
|
89
|
+
description={option.desc}
|
|
90
|
+
showDescription
|
|
91
|
+
role="button"
|
|
92
|
+
tabIndex={0}
|
|
93
|
+
onClick={() => setSelectedOption(option.key)}
|
|
94
|
+
onKeyDown={(e) => {
|
|
95
|
+
if (e.key === "Enter" || e.key === " ") { e.preventDefault(); setSelectedOption(option.key); }
|
|
96
|
+
}}
|
|
97
|
+
/>
|
|
98
|
+
{idx < OPTIONS.length - 1 && <div className="or-separator">or</div>}
|
|
99
|
+
</Fragment>
|
|
100
|
+
))}
|
|
101
|
+
|
|
102
|
+
// Title-only card
|
|
103
|
+
<ScDefaultCard title="Start from scratch" showDescription={false} role="button" tabIndex={0} onClick={go} />
|
|
104
|
+
|
|
105
|
+
// Design-parity screenshot of the hover skin (never wire this to onMouseEnter)
|
|
106
|
+
<ScDefaultCard title="Use your own taxonomy" description="Average Time : 30 mins." state="hover" />
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## 2. Where to use it
|
|
112
|
+
|
|
113
|
+
- **Catalogix "Choose your store taxonomy"** — three stacked cards ("Use Catalogix
|
|
114
|
+
taxonomy" / "Use your own taxonomy" / "Copy from existing store"), separated by
|
|
115
|
+
"or".
|
|
116
|
+
- **Catalogix "Add Active Feed" → Connect options** — the same control, reused for
|
|
117
|
+
feed connection methods. The call site's own comment records that this card
|
|
118
|
+
*replaced* a hand-rolled `.option` + `.hr-divider-sm` block.
|
|
119
|
+
- Any **empty state or drawer that offers 2–4 mutually exclusive routes**, inside
|
|
120
|
+
`ScModal` / `ScDrawer` or a page-level empty state.
|
|
121
|
+
|
|
122
|
+
It composes nothing from the DS and is composed by nothing — you always place it.
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## 3. When to use it
|
|
127
|
+
|
|
128
|
+
### Use it when
|
|
129
|
+
|
|
130
|
+
- The card is a **navigation/branching choice**, and clicking it immediately does
|
|
131
|
+
something (opens a modal, pushes a route, selects a method).
|
|
132
|
+
- The content is exactly **title + optional one-line hint**, centred.
|
|
133
|
+
- Cards are stacked full-width, not tiled in a grid.
|
|
134
|
+
|
|
135
|
+
### Don't use it — reach for this instead
|
|
136
|
+
|
|
137
|
+
| Situation | Use instead |
|
|
138
|
+
|---|---|
|
|
139
|
+
| Tile with an icon chip in a product grid | `ScAppListingCard` |
|
|
140
|
+
| Tile in the app-switcher grid (gradient border, `active`) | `ScAppCardV3` |
|
|
141
|
+
| Store summary (name, product count, status beacon) | `ScStoreCard` |
|
|
142
|
+
| A source→target mapping row with confirm/ignore lifecycle | `ScMappingCard` |
|
|
143
|
+
| A value-mapping/curation row with an "updated" dot | `ScValueMappingL1` |
|
|
144
|
+
| A **saved** single-choice form value | `ScRadio` (list) or `ScTabField` (segmented) |
|
|
145
|
+
| A filter/segmented view switch | `ScSelectionPill` / `ScSelectionPillGroup` |
|
|
146
|
+
| A row in a table | `ScTableList` / `ScCatalogixStoreTableList` |
|
|
147
|
+
| An agent quick-prompt card | `ScBriefCard` (via `ScQuickPrompt`) |
|
|
148
|
+
| The card needs a CTA button inside it | `ScPlanCard` / `ScWorkspaceSwitchCard`, or compose your own with `ScButton` |
|
|
149
|
+
|
|
150
|
+
### Don't confuse with
|
|
151
|
+
|
|
152
|
+
| You may actually want | Not this |
|
|
153
|
+
|---|---|
|
|
154
|
+
| `ScAppListingCard` — icon + left-aligned title + description, scale-up hover, grid tile | `ScDefaultCard` is centred, full-width, chrome-light |
|
|
155
|
+
| `ScBriefCard` — centred description-only card with a coral gradient border (agent runtime) | This card has a plain subtle border and a title |
|
|
156
|
+
| `ScMappingCard` — three-status lifecycle + action footer | This card has no states beyond default/hover |
|
|
157
|
+
| `ScRadio` — a real form control with a selected state | This card has **no selected state at all** (see Gotcha 4) |
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## 4. Why to use it
|
|
162
|
+
|
|
163
|
+
- **It removes a hand-rolled pattern that already existed twice.** The Catalogix
|
|
164
|
+
connect-options screen and the choose-taxonomy screen had independently built the
|
|
165
|
+
same box; both now render this card, so the padding, radius, hairline border and
|
|
166
|
+
hover feel are identical.
|
|
167
|
+
- **Light-mode-safe hover.** The hover recipe changes *both* the background and the
|
|
168
|
+
border. Because light mode collapses all `surface-*` tokens to white, the border
|
|
169
|
+
step is what keeps the hover legible — a hand-rolled card that only changes
|
|
170
|
+
background loses its hover entirely in light mode.
|
|
171
|
+
- **The hairline border is 0.5px** (`0.03125rem`), matching `ScStoreCard` and the
|
|
172
|
+
divider family rather than the 1px used by the app cards — consistent with the
|
|
173
|
+
Catalogix card language.
|
|
174
|
+
- **`state="hover"` gives you deterministic screenshots** for Figma parity checks
|
|
175
|
+
without simulating pointer events (headless Chrome cannot force `:hover`
|
|
176
|
+
reliably).
|
|
177
|
+
- **`word-break: break-word` on both lines**, so a long taxonomy name never blows
|
|
178
|
+
out the card width.
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## Gotchas
|
|
183
|
+
|
|
184
|
+
**1. Placeholder defaults ship.** `title="Title"` and `description="Description"`
|
|
185
|
+
are real strings.
|
|
186
|
+
|
|
187
|
+
```tsx
|
|
188
|
+
// WRONG — renders "Title" / "Description"
|
|
189
|
+
<ScDefaultCard onClick={go} />
|
|
190
|
+
|
|
191
|
+
// RIGHT
|
|
192
|
+
<ScDefaultCard title="Copy from existing store" description="Average Time : 1 min." onClick={go} />
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
**2. Not keyboard accessible on its own.** `cursor: pointer` says "click me" but
|
|
196
|
+
there is no `role`, `tabIndex`, `onKeyDown` or focus ring. Always add:
|
|
197
|
+
|
|
198
|
+
```tsx
|
|
199
|
+
<ScDefaultCard
|
|
200
|
+
title={o.title}
|
|
201
|
+
description={o.desc}
|
|
202
|
+
role="button"
|
|
203
|
+
tabIndex={0}
|
|
204
|
+
onClick={pick}
|
|
205
|
+
onKeyDown={(e) => { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); pick(); } }}
|
|
206
|
+
/>
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
**3. `description=""` hides the line even with `showDescription` true.** The guard is
|
|
210
|
+
`showDescription && Boolean(description)`. That is usually what you want, but it
|
|
211
|
+
means an empty string and `showDescription={false}` are indistinguishable, and the
|
|
212
|
+
card's height changes between them — watch out in equal-height rows.
|
|
213
|
+
|
|
214
|
+
**4. There is no selected/active state.** `state` only has `default` and `hover`. If
|
|
215
|
+
your flow needs to show which option is currently chosen, you must add it via
|
|
216
|
+
`className` (or use `ScRadio` / `ScTabField` / `ScSelectionPill` instead). Both
|
|
217
|
+
Catalogix screens dodge this by navigating away on click.
|
|
218
|
+
|
|
219
|
+
**5. Hover's background change is invisible in light mode.** `surface-base` and
|
|
220
|
+
`surface-basesubtle` are both `#ffffff` in the light theme; only the border darkens.
|
|
221
|
+
Do not rely on the fill to communicate hover.
|
|
222
|
+
|
|
223
|
+
**6. `width: 100%` is baked in.** The card always fills its parent. To get a narrower
|
|
224
|
+
card, constrain the parent — setting `width` via `className` fights the module class
|
|
225
|
+
at equal specificity (yours wins because it is appended, but inline `style` is safer).
|
|
226
|
+
|
|
227
|
+
**7. `state="hover"` is design parity, not interaction.** Never drive it from
|
|
228
|
+
`onMouseEnter`; you would double up on the real `:hover` and break touch devices.
|
|
229
|
+
|
|
230
|
+
**8. No icon slot.** If your design shows a glyph above the title, this is the wrong
|
|
231
|
+
card — use `ScAppListingCard`, or render your own icon above a `ScDefaultCard`
|
|
232
|
+
(the Catalogix taxonomy screen puts `SiconStores` *outside* the cards, above the
|
|
233
|
+
heading).
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## In the wild
|
|
238
|
+
|
|
239
|
+
```tsx
|
|
240
|
+
// catalogix/dashboard app/containers/Products/index.jsx:1684
|
|
241
|
+
<ScDefaultCard
|
|
242
|
+
title="Use Catalogix taxonomy"
|
|
243
|
+
description="Average Time : Instant."
|
|
244
|
+
role="button"
|
|
245
|
+
tabIndex={0}
|
|
246
|
+
onClick={() => {
|
|
247
|
+
setShowCurationModal(true);
|
|
248
|
+
}}
|
|
249
|
+
onKeyDown={(e) => {
|
|
250
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
251
|
+
e.preventDefault();
|
|
252
|
+
setShowCurationModal(true);
|
|
253
|
+
}
|
|
254
|
+
}}
|
|
255
|
+
/>
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
Also at `app/containers/StoreSettingsV2/FeedImport/Feed/ConnectOptions/index.jsx:67`
|
|
259
|
+
(feed connect methods) and twice more in `Products/index.jsx` (lines 1703, 1728).
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## Related
|
|
264
|
+
|
|
265
|
+
- `ScMappingCard` — the feed-mapping card when you need a confirm/ignore lifecycle.
|
|
266
|
+
- `ScStoreCard` — the store-listing card (name + beacon + counts).
|
|
267
|
+
- `ScAppListingCard` / `ScAppCardV3` — icon-bearing product tiles for grids.
|
|
268
|
+
- `ScRadio` / `ScTabField` / `ScSelectionPillGroup` — when the choice is a saved value.
|
|
269
|
+
- `ScModal` / `ScDrawer` — the containers these cards usually sit in.
|