@streamoid/ui 0.6.17 → 0.6.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +36 -36
- package/dist/index.d.mts +10 -0
- package/dist/index.d.ts +10 -0
- package/package.json +3 -2
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
---
|
|
2
|
+
component: ScStoreCard
|
|
3
|
+
package: "@streamoid/ui"
|
|
4
|
+
category: cards
|
|
5
|
+
status: stable
|
|
6
|
+
renders: div
|
|
7
|
+
tags: [card, store, tile, listing, grid, beacon, status, products, catalogix]
|
|
8
|
+
related: [ScBeacon, ScHDivider, ScCatalogixStoreHeader, ScCatalogixStoreTableList, ScDefaultCard]
|
|
9
|
+
do_not_confuse_with: [ScCatalogixStoreTableList, ScDefaultCard, ScAppListingCard, ScWorkspaceCard]
|
|
10
|
+
used_by: [catalogix]
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# ScStoreCard
|
|
14
|
+
|
|
15
|
+
**One store in the Catalogix stores grid.** A two-line-clamped store name on top, a
|
|
16
|
+
hairline divider, then a footer row: status beacon, product count on the left, and
|
|
17
|
+
the creation date pushed right. Scales up 1% on hover.
|
|
18
|
+
|
|
19
|
+
## TL;DR for agents
|
|
20
|
+
|
|
21
|
+
- **Reach for it when:** you are rendering the **grid** view of a stores listing and
|
|
22
|
+
each tile is name + status + counts + date.
|
|
23
|
+
- **Don't reach for it when:** you are rendering the **list** view of the same data
|
|
24
|
+
(→ `ScCatalogixStoreHeader` + `ScCatalogixStoreTableList`), or the card is a
|
|
25
|
+
generic "choose an option" box (→ `ScDefaultCard`).
|
|
26
|
+
- **Four things that will bite you:**
|
|
27
|
+
1. Every content prop has a real default — a bare `<ScStoreCard />` renders
|
|
28
|
+
`"Store Name"`, `"1490 Products"`, `"24th Jan 2026"`.
|
|
29
|
+
2. `noOfProducts` and `dateCreated` are **pre-formatted strings**, including the
|
|
30
|
+
word "Products" and the date format. The card does no formatting.
|
|
31
|
+
3. The name block has a **fixed `height: 3.5rem`** with a 2-line clamp, so short
|
|
32
|
+
names still reserve two lines (good for grid alignment, surprising in a
|
|
33
|
+
one-off).
|
|
34
|
+
4. The CSS styles `:focus-visible` but the component sets **no `tabIndex`** — you
|
|
35
|
+
must add `role="button" tabIndex={0} onKeyDown` for that styling to ever fire.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## 1. How to use it
|
|
40
|
+
|
|
41
|
+
### Import
|
|
42
|
+
|
|
43
|
+
```tsx
|
|
44
|
+
import { ScStoreCard } from "@streamoid/ui";
|
|
45
|
+
import "@streamoid/ui/dist/index.css"; // once, at your app root
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Minimal usage
|
|
49
|
+
|
|
50
|
+
```tsx
|
|
51
|
+
<ScStoreCard
|
|
52
|
+
storeName="SS26 Womenswear"
|
|
53
|
+
noOfProducts="1490 Products"
|
|
54
|
+
dateCreated="24th Jan 2026"
|
|
55
|
+
tone="success"
|
|
56
|
+
/>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Props
|
|
60
|
+
|
|
61
|
+
| Prop | Type | Default | Notes |
|
|
62
|
+
|---|---|---|---|
|
|
63
|
+
| `storeName` | `string` | `"Store Name"` | ⚠️ Real default. `lead-text-xs-regular`, clamped to 2 lines in a fixed 3.5rem block, and wired to a native `title` tooltip so the clipped text is still readable on hover. |
|
|
64
|
+
| `noOfProducts` | `string` | `"1490 Products"` | ⚠️ Real default, **including the unit word**. Left-aligned, `flex: 1`, single-line ellipsised. |
|
|
65
|
+
| `dateCreated` | `string` | `"24th Jan 2026"` | ⚠️ Real default. Right-aligned, `flex-shrink: 0`, single-line ellipsised. |
|
|
66
|
+
| `tone` | `ScBeaconTone` = `"success" \| "warning" \| "error" \| "neutral"` | `"neutral"` | Colour of the 20px `ScBeacon` dot in the footer. `neutral` = muted grey. |
|
|
67
|
+
| `className` | `string` | – | Appended after the internal class (guarded — no stray `undefined` class). |
|
|
68
|
+
| `...props` | `HTMLAttributes<HTMLDivElement>` | – | `onClick`, `role`, `tabIndex`, `onKeyDown`, `style`, `aria-*`, `data-*` land on the root div. |
|
|
69
|
+
|
|
70
|
+
### Tone semantics
|
|
71
|
+
|
|
72
|
+
| `tone` | Beacon colour token | Typical meaning in a stores grid |
|
|
73
|
+
|---|---|---|
|
|
74
|
+
| `success` | `--alias-text-and-icons-success` | Store live / feed healthy |
|
|
75
|
+
| `warning` | `--alias-text-and-icons-warning` | Processing / partial |
|
|
76
|
+
| `error` | `--alias-text-and-icons-error` | Failed / status fetch failed |
|
|
77
|
+
| `neutral` | `--alias-text-and-icons-muted` | Unknown / not yet reported (the default) |
|
|
78
|
+
|
|
79
|
+
### Recipes
|
|
80
|
+
|
|
81
|
+
```tsx
|
|
82
|
+
// The Catalogix idiom — grid view, fully keyboard reachable
|
|
83
|
+
<div className="stores-grid">
|
|
84
|
+
{stores.map((store) => {
|
|
85
|
+
const meta = getStoreMeta(store); // derives label strings + tone
|
|
86
|
+
return (
|
|
87
|
+
<ScStoreCard
|
|
88
|
+
key={store._id}
|
|
89
|
+
storeName={store.name}
|
|
90
|
+
noOfProducts={meta.productCountLabel} // e.g. "1490 Products" / "—"
|
|
91
|
+
dateCreated={meta.dateLabel}
|
|
92
|
+
tone={meta.tone}
|
|
93
|
+
role="button"
|
|
94
|
+
tabIndex={0}
|
|
95
|
+
onClick={() => openStore(store)}
|
|
96
|
+
onKeyDown={(e) => {
|
|
97
|
+
if (e.key === "Enter" || e.key === " ") { e.preventDefault(); openStore(store); }
|
|
98
|
+
}}
|
|
99
|
+
/>
|
|
100
|
+
);
|
|
101
|
+
})}
|
|
102
|
+
</div>
|
|
103
|
+
|
|
104
|
+
// Loading / failed metadata — the card takes whatever string you give it
|
|
105
|
+
<ScStoreCard storeName={store.name} noOfProducts="Loading…" dateCreated="—" tone="neutral" />
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## 2. Where to use it
|
|
111
|
+
|
|
112
|
+
- **Catalogix `StoresListing`, grid view.** The same screen's list view swaps to
|
|
113
|
+
`ScCatalogixStoreHeader` + `ScCatalogixStoreTableList` from the same `getStoreMeta`
|
|
114
|
+
data — keep the two branches fed identically.
|
|
115
|
+
- Any future **"collection of containers" grid** (stores, catalogues, feeds) where a
|
|
116
|
+
tile is a name plus two metrics and a status dot.
|
|
117
|
+
|
|
118
|
+
It composes `ScBeacon` (the status dot) and `ScHDivider` (the hairline between name
|
|
119
|
+
and footer) from the DS; everything else is its own CSS.
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## 3. When to use it
|
|
124
|
+
|
|
125
|
+
### Use it when
|
|
126
|
+
|
|
127
|
+
- The user is **choosing which store to open**, and the tile's job is identity plus
|
|
128
|
+
at-a-glance health.
|
|
129
|
+
- You are in a grid and want **uniform tile heights** without measuring — the fixed
|
|
130
|
+
name block gives you that for free.
|
|
131
|
+
- The status is a single dot, not a labelled chip.
|
|
132
|
+
|
|
133
|
+
### Don't use it — reach for this instead
|
|
134
|
+
|
|
135
|
+
| Situation | Use instead |
|
|
136
|
+
|---|---|
|
|
137
|
+
| The list/table view of the same stores | `ScCatalogixStoreHeader` + `ScCatalogixStoreTableList` |
|
|
138
|
+
| A generic table row | `ScTableHeader` + `ScTableList` (`ScTableListMobile` on mobile) |
|
|
139
|
+
| A generic "pick one option" card | `ScDefaultCard` |
|
|
140
|
+
| A product/app tile with an icon chip | `ScAppListingCard` |
|
|
141
|
+
| A workspace, not a store | `ScWorkspaceSwitchCard` / `StreamoidWorkspaceSwitcher` |
|
|
142
|
+
| A labelled status chip rather than a dot | `ScBadges` |
|
|
143
|
+
| The status dot alone, in your own layout | `ScBeacon` |
|
|
144
|
+
| A feed source→target mapping row | `ScMappingCard` |
|
|
145
|
+
|
|
146
|
+
### Don't confuse with
|
|
147
|
+
|
|
148
|
+
| You may actually want | Not this |
|
|
149
|
+
|---|---|
|
|
150
|
+
| `ScCatalogixStoreTableList` — the row form of a store, with the header component | `ScStoreCard` is the grid form; same data, different view |
|
|
151
|
+
| `ScDefaultCard` — centred title + hint, no footer, no divider, no beacon | This card has a name block, divider and metrics footer |
|
|
152
|
+
| `ScWorkspaceCard` — workspace identity with badges and buttons | Different entity, different (legacy) component |
|
|
153
|
+
| `ScAppListingCard` — icon + title + description product tile | No icon here; the beacon is the only glyph |
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## 4. Why to use it
|
|
158
|
+
|
|
159
|
+
- **Grid alignment without measuring.** The `height: 3.5rem` + `-webkit-line-clamp: 2`
|
|
160
|
+
name block means every tile is the same height regardless of name length — the
|
|
161
|
+
usual reason hand-rolled store grids look ragged.
|
|
162
|
+
- **The clipped name still has a tooltip.** `title={storeName}` is wired internally,
|
|
163
|
+
so a two-line-clamped name is recoverable on hover. Easy to forget by hand.
|
|
164
|
+
- **Status colour comes from `ScBeacon`**, i.e. from
|
|
165
|
+
`--alias-text-and-icons-success/warning/error/muted` — the same four colours every
|
|
166
|
+
other status in the product uses, and `aria-hidden` so it does not pollute the
|
|
167
|
+
accessible name.
|
|
168
|
+
- **Hover survives light mode.** Background (`base` → `basesubtle`), border
|
|
169
|
+
(`subtle` → `default`) *and* `transform: scale(1.01)` all change together; because
|
|
170
|
+
light mode collapses the surfaces to white, the border and the scale are what keep
|
|
171
|
+
the hover legible.
|
|
172
|
+
- **`overflow: hidden` + 1.125rem radius** means the divider and footer can never
|
|
173
|
+
poke past the rounded corners.
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## Gotchas
|
|
178
|
+
|
|
179
|
+
**1. Placeholder defaults are real content.** `"Store Name"`, `"1490 Products"` and
|
|
180
|
+
`"24th Jan 2026"` will ship if you forget a prop — and `"1490 Products"` looks
|
|
181
|
+
plausible enough to survive review.
|
|
182
|
+
|
|
183
|
+
**2. You format, the card renders.** `noOfProducts` includes the unit; `dateCreated`
|
|
184
|
+
includes the date format. There is no number or date formatting inside.
|
|
185
|
+
|
|
186
|
+
```tsx
|
|
187
|
+
// WRONG — renders the bare number with no unit
|
|
188
|
+
<ScStoreCard storeName={s.name} noOfProducts={String(s.count)} />
|
|
189
|
+
|
|
190
|
+
// RIGHT
|
|
191
|
+
<ScStoreCard storeName={s.name} noOfProducts={`${s.count} Products`} />
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
**3. `overflow: hidden` on the root clips popovers.** A kebab menu or tooltip opened
|
|
195
|
+
from inside the card gets cut off. Portal it to `document.body` with an explicit
|
|
196
|
+
z-index, or place the trigger outside the card.
|
|
197
|
+
|
|
198
|
+
**4. `:focus-visible` styling is dead until you add `tabIndex`.** The CSS defines a
|
|
199
|
+
focus-visible skin (same as hover, outline removed), but the component ships no
|
|
200
|
+
`tabIndex` and no key handling. Add `role="button" tabIndex={0} onKeyDown` — the
|
|
201
|
+
Catalogix call site does exactly this.
|
|
202
|
+
|
|
203
|
+
**5. `cursor: pointer` is unconditional.** A read-only card still looks clickable.
|
|
204
|
+
Override with `style={{ cursor: "default" }}` when there is no `onClick`.
|
|
205
|
+
|
|
206
|
+
**6. `transform: scale(1.01)` on hover.** Small, but it does lift the tile over its
|
|
207
|
+
neighbours with no `z-index` management. Keep grid gaps ≥ 12px.
|
|
208
|
+
|
|
209
|
+
**7. The name block reserves two lines even for one-word names.** Correct in a grid,
|
|
210
|
+
odd if you render a single card in a sidebar. There is no prop to collapse it.
|
|
211
|
+
|
|
212
|
+
**8. `tone` defaults to `neutral`, not `success`.** A store whose status you have not
|
|
213
|
+
fetched yet shows a grey dot — which is right, but means "no tone passed" reads as
|
|
214
|
+
"unknown", not "healthy".
|
|
215
|
+
|
|
216
|
+
**9. The beacon is `aria-hidden`.** Screen readers get name + counts + date only. If
|
|
217
|
+
status matters for accessibility, add an `aria-label` on the card or a visually
|
|
218
|
+
hidden status string.
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## In the wild
|
|
223
|
+
|
|
224
|
+
```tsx
|
|
225
|
+
// catalogix/dashboard app/containers/StoresListing/index.jsx:354
|
|
226
|
+
<ScStoreCard
|
|
227
|
+
key={store._id}
|
|
228
|
+
storeName={store.name}
|
|
229
|
+
noOfProducts={meta.productCountLabel}
|
|
230
|
+
dateCreated={meta.dateLabel}
|
|
231
|
+
tone={meta.tone}
|
|
232
|
+
role="button"
|
|
233
|
+
tabIndex={0}
|
|
234
|
+
onClick={() => openStore(store)}
|
|
235
|
+
onKeyDown={(e) => {
|
|
236
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
237
|
+
e.preventDefault();
|
|
238
|
+
openStore(store);
|
|
239
|
+
}
|
|
240
|
+
}}
|
|
241
|
+
/>
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
## Related
|
|
247
|
+
|
|
248
|
+
- `ScBeacon` — the status dot this card renders; use it standalone in your own rows.
|
|
249
|
+
- `ScHDivider` — the hairline between name and footer.
|
|
250
|
+
- `ScCatalogixStoreHeader` / `ScCatalogixStoreTableList` — the list-view twin of this card.
|
|
251
|
+
- `ScDefaultCard` — generic option card when there is no store metadata.
|
|
252
|
+
- `ScBadges` — a labelled status chip when a dot is not enough.
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
---
|
|
2
|
+
component: ScStrLogo
|
|
3
|
+
package: "@streamoid/ui"
|
|
4
|
+
category: brand
|
|
5
|
+
status: legacy
|
|
6
|
+
renders: svg
|
|
7
|
+
tags: [logo, wordmark, streamoid, mascot, lockup, brand, legacy, 626x60]
|
|
8
|
+
related: [ScStreamoidWordmark, ScStreamoidMascot, ScSideBarLogoUnit, ScLogoUnit, ScAppcardLogos]
|
|
9
|
+
do_not_confuse_with: [ScStreamoidWordmark, ScStreamoidMascot, ScLogoUnit, ScSideBarLogoUnit, ScAppcardLogos]
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# ScStrLogo
|
|
13
|
+
|
|
14
|
+
**The legacy Streamoid corporate lockup: the "streamoid" wordmark *and* the mascot
|
|
15
|
+
in one 626×60 SVG.** One inert `<svg>` with hardcoded `width="626" height="60"`;
|
|
16
|
+
the letterforms are painted with a text token, and the mascot half mixes a fixed
|
|
17
|
+
teal→purple gradient (two arcs) with a third arc painted in that same text token.
|
|
18
|
+
|
|
19
|
+
> **Legacy.** For new work use `ScStreamoidWordmark` (110×16 wordmark) and
|
|
20
|
+
> `ScStreamoidMascot` (the glyph alone), passed into `ScSideBarLogoUnit`. Its only
|
|
21
|
+
> in-library consumer is `ScLogoUnit`, which is itself superseded by
|
|
22
|
+
> `ScSideBarLogoUnit` / `StreamoidSidebar`. It is not marked `@deprecated` in the
|
|
23
|
+
> source, so it still compiles and ships — it simply isn't the current path.
|
|
24
|
+
|
|
25
|
+
## TL;DR for agents
|
|
26
|
+
|
|
27
|
+
- **Reach for it when:** you specifically need the **combined** wordmark + mascot
|
|
28
|
+
lockup at large size (a splash / auth / print-ish surface), and you are willing
|
|
29
|
+
to size it yourself. That combination exists nowhere else in the library.
|
|
30
|
+
- **Don't reach for it when:** you're filling a sidebar header (→
|
|
31
|
+
`ScSideBarLogoUnit` with `ScStreamoidWordmark` / `ScStreamoidMascot`), you want
|
|
32
|
+
just the wordmark (→ `ScStreamoidWordmark`), or just the mascot (→
|
|
33
|
+
`ScStreamoidMascot`).
|
|
34
|
+
- **Four things that will bite you:**
|
|
35
|
+
1. It renders **626px wide** by default and will blow out any normal container.
|
|
36
|
+
There is no size prop — you must override width/height via `className`.
|
|
37
|
+
2. `type="logo-only"` does **not** hide the wordmark. It just shrinks the whole
|
|
38
|
+
lockup into a 163px box.
|
|
39
|
+
3. Every prop except `type` and `className` is dropped — `...props` is
|
|
40
|
+
destructured and never spread, and the interface doesn't extend
|
|
41
|
+
`HTMLAttributes`.
|
|
42
|
+
4. The gradient `id` is **hardcoded**, so two instances on a page produce
|
|
43
|
+
duplicate DOM ids.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 1. How to use it
|
|
48
|
+
|
|
49
|
+
### Import
|
|
50
|
+
|
|
51
|
+
```tsx
|
|
52
|
+
import { ScStrLogo } from "@streamoid/ui";
|
|
53
|
+
import "@streamoid/ui/dist/index.css"; // once, at your app root
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Minimal usage
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
// Renders at 626×60 — almost always too big. Size it with a class.
|
|
60
|
+
<ScStrLogo className="myLogo" />
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
```css
|
|
64
|
+
/* your stylesheet — the only way to size it */
|
|
65
|
+
.myLogo { width: 167px; height: 16px; }
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Props
|
|
69
|
+
|
|
70
|
+
| Prop | Type | Default | Notes |
|
|
71
|
+
|---|---|---|---|
|
|
72
|
+
| `type` | `"default"` \| `"logo-only"` | `"default"` | Adds `.type-default` / `.type-logo-only`. ⚠️ `logo-only` only constrains the box to `163×60` + `aspect-ratio: 163/60` — it does **not** clip to the mascot (Gotcha 2). |
|
|
73
|
+
| `className` | `string` | – | Concatenated after the internal classes. **The only way to change its size.** |
|
|
74
|
+
| `...props` | — | – | ⚠️ Destructured but **never spread**. `onClick`, `style`, `id`, `aria-*` are also type errors — the props interface does not extend `React.SVGProps`/`HTMLAttributes`. |
|
|
75
|
+
|
|
76
|
+
### What each `type` actually does
|
|
77
|
+
|
|
78
|
+
| `type` | CSS applied | Rendered result |
|
|
79
|
+
|---|---|---|
|
|
80
|
+
| `"default"` | `height: 3.75rem` (60px); width comes from the SVG's own `width="626"` | Full lockup, 626×60 |
|
|
81
|
+
| `"logo-only"` | `height: 3.75rem`, `width: 10.1875rem` (163px), `aspect-ratio: 163/60` | The **same** full lockup, uniformly scaled down to ~163×15.6 and vertically centred in a 60px box |
|
|
82
|
+
|
|
83
|
+
### Recipes
|
|
84
|
+
|
|
85
|
+
```tsx
|
|
86
|
+
// Splash / auth screen — one clear legitimate use, sized by a wrapper class
|
|
87
|
+
<div className="authBrand">
|
|
88
|
+
<ScStrLogo />
|
|
89
|
+
</div>
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
```css
|
|
93
|
+
.authBrand :global(svg) { width: 313px; height: 30px; } /* keep 626:60 */
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
```tsx
|
|
97
|
+
// What you almost certainly want instead
|
|
98
|
+
<ScStreamoidWordmark width={165} height={24} /> {/* wordmark only */}
|
|
99
|
+
<ScStreamoidMascot size={40} /> {/* mascot only */}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## 2. Where to use it
|
|
105
|
+
|
|
106
|
+
- **Historically:** inside `ScLogoUnit`, which wrapped it in a 240px padded sidebar
|
|
107
|
+
box and forced it down to `167×16` (expanded) or `32×12` (collapsed) with
|
|
108
|
+
`!important` width/height overrides. That pair was the pre-`StreamoidSidebar`
|
|
109
|
+
sidebar header.
|
|
110
|
+
- **Today:** nothing renders it in any host app. The sidebar header is
|
|
111
|
+
`ScSideBarLogoUnit`; large-format brand surfaces are better served by
|
|
112
|
+
`ScStreamoidWordmark` at an explicit size.
|
|
113
|
+
|
|
114
|
+
Photogenix evaluated `ScLogoUnit`/`ScStrLogo` during its DS migration and
|
|
115
|
+
deliberately rejected them — the corporate lockup would have erased the *product*
|
|
116
|
+
wordmark that distinguishes each app (`dashboard/docs/archive/Migration-leftout.md`).
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## 3. When to use it
|
|
121
|
+
|
|
122
|
+
### Use it when
|
|
123
|
+
|
|
124
|
+
- You genuinely need **wordmark + mascot together** as a single mark, at a size
|
|
125
|
+
where both are legible (≥ ~200px wide), and you can supply the sizing CSS.
|
|
126
|
+
- You are maintaining an existing `ScLogoUnit` call site and don't want to migrate
|
|
127
|
+
it yet.
|
|
128
|
+
|
|
129
|
+
### Don't use it — reach for this instead
|
|
130
|
+
|
|
131
|
+
| Situation | Use instead |
|
|
132
|
+
|---|---|
|
|
133
|
+
| Sidebar header, expanded | `ScSideBarLogoUnit` + `ScStreamoidWordmark` |
|
|
134
|
+
| Sidebar header, collapsed | `ScSideBarLogoUnit state="collapsed"` + `ScStreamoidMascot` |
|
|
135
|
+
| Wordmark on its own, any size, theme-correct | `ScStreamoidWordmark` (`width`/`height`/`color` props) |
|
|
136
|
+
| Mascot glyph on its own | `ScStreamoidMascot` (`size` prop) |
|
|
137
|
+
| A **product** wordmark (Artifax / Photogenix / Catalogix / Tactix) | `ScAppcardLogos` or `ScSideBarLogoUnit product="…"` |
|
|
138
|
+
| The CXO Copilot lockup | `ScCxoCopilotLogo` |
|
|
139
|
+
| A clickable logo | `ScSideBarLogoUnit`, or your own `<button>` wrapper — this svg takes no handlers |
|
|
140
|
+
| Anything that must be recoloured per surface | `ScStreamoidWordmark` (`color` prop) — `ScStrLogo` has no colour prop |
|
|
141
|
+
|
|
142
|
+
### Don't confuse with
|
|
143
|
+
|
|
144
|
+
| You may actually want | Not this |
|
|
145
|
+
|---|---|
|
|
146
|
+
| `ScStreamoidWordmark` — 110×16 plain wordmark, mask-painted by a token, `width`/`height`/`color` props | `ScStrLogo` is the 626×60 wordmark **+ mascot**, unsizeable by prop |
|
|
147
|
+
| `ScStreamoidMascot` — the mascot alone, `size` prop, unique gradient id per instance | `ScStrLogo` always includes the wordmark and reuses one hardcoded gradient id |
|
|
148
|
+
| `ScLogoUnit` — the padded 240px **container** that renders `ScStrLogo` | Also legacy; the current container is `ScSideBarLogoUnit` (capital **B**) |
|
|
149
|
+
| `ScSideBarLogoUnit` — the current interactive sidebar header row | `ScStrLogo` is an inert mark |
|
|
150
|
+
| `ScAppcardLogos` — per-product wordmarks | Contains no Streamoid entry |
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## 4. Why to use it
|
|
155
|
+
|
|
156
|
+
Honestly: mostly for continuity. What it does give you:
|
|
157
|
+
|
|
158
|
+
- **The only combined lockup in the library** — wordmark and mascot in one mark,
|
|
159
|
+
in the correct relative proportions.
|
|
160
|
+
- **Theme-aware letterforms.** The ten letterform paths are filled with
|
|
161
|
+
`--alias-text-and-icons-primary` (an alias of `--alias-text---icons-primary`),
|
|
162
|
+
so the wordmark half flips with the theme instead of staying #F5F5F5. Of the
|
|
163
|
+
mascot's three arcs, only two carry the brand gradient (`paint0_linear_19_1153`);
|
|
164
|
+
the right-hand arc is filled with that same text token — an eleventh token-filled
|
|
165
|
+
path — so part of the glyph flips with the theme too.
|
|
166
|
+
- **No asset shipping.** Same argument as the rest of SC-Brand: hosts carry no
|
|
167
|
+
brand SVGs. (CXO still has two hand-exported copies at
|
|
168
|
+
`src/app/components/strLogo/` that nothing imports — that's the mess this exists
|
|
169
|
+
to end.)
|
|
170
|
+
|
|
171
|
+
What you *don't* get, and why `ScStreamoidWordmark` superseded it: no size props,
|
|
172
|
+
no colour prop, no per-instance gradient id, no a11y wiring, no event props.
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## Gotchas
|
|
177
|
+
|
|
178
|
+
**1. It is 626px wide until you say otherwise.** The `<svg>` carries
|
|
179
|
+
`width="626" height="60"`, and the CSS sets only `height: 3.75rem`. Dropping it
|
|
180
|
+
into a sidebar or card will overflow.
|
|
181
|
+
|
|
182
|
+
```tsx
|
|
183
|
+
// WRONG — 626px wide inside a 240px rail
|
|
184
|
+
<ScStrLogo />
|
|
185
|
+
|
|
186
|
+
// RIGHT — constrain it, keeping the 626:60 ratio
|
|
187
|
+
<ScStrLogo className={styles.brand} /> /* .brand { width: 167px; height: 16px } */
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
**2. `type="logo-only"` is a misnomer.** It applies `width: 163px` +
|
|
191
|
+
`aspect-ratio: 163/60`; the SVG's default `preserveAspectRatio` then scales the
|
|
192
|
+
*entire* 626-unit viewBox down to fit that width (≈163×15.6, vertically centred).
|
|
193
|
+
The wordmark is still there, just tiny. For the mascot alone use
|
|
194
|
+
`ScStreamoidMascot`.
|
|
195
|
+
|
|
196
|
+
**3. All other props are silently dropped.**
|
|
197
|
+
|
|
198
|
+
```tsx
|
|
199
|
+
// WRONG — both are type errors, and even with a cast nothing is spread onto the svg
|
|
200
|
+
<ScStrLogo onClick={goHome} style={{ width: 200 }} />
|
|
201
|
+
|
|
202
|
+
// RIGHT
|
|
203
|
+
<button type="button" onClick={goHome} aria-label="Home" className={styles.brandBtn}>
|
|
204
|
+
<ScStrLogo />
|
|
205
|
+
</button>
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
**4. The gradient id is hardcoded** (`paint0_linear_19_1153`). Render two
|
|
209
|
+
`ScStrLogo`s and the document contains two elements with the same `id`; every
|
|
210
|
+
instance resolves `url(#paint0_linear_19_1153)` to the *first* one, so unmounting
|
|
211
|
+
that first instance can strip the gradient from the rest. `ScStreamoidMascot` and
|
|
212
|
+
`ScCxoCopilotLogo` avoid this with `useId()`.
|
|
213
|
+
|
|
214
|
+
**5. Omitting `className` puts the literal string `undefined` in the class
|
|
215
|
+
attribute.** `className={styles.scStrLogo + " " + className + " " + variantsClassName}`
|
|
216
|
+
is unguarded, so you get `class="ScStrLogo_scStrLogo undefined ScStrLogo_type-default"`.
|
|
217
|
+
Harmless visually, but don't write selectors or tests against the class list.
|
|
218
|
+
|
|
219
|
+
**6. No `role`, no `aria-label`, no `<title>`, and not `aria-hidden`.** It is
|
|
220
|
+
neither properly labelled nor properly hidden. Add `aria-hidden` on a wrapper if
|
|
221
|
+
it's decorative, or label the wrapper if it carries meaning.
|
|
222
|
+
|
|
223
|
+
**7. `.vector` in the stylesheet is dead code.** The CSS defines
|
|
224
|
+
`.type-default .vector` / `.type-logo-only .vector`, but the component never
|
|
225
|
+
renders an element with that class. Don't try to target it.
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## In the wild
|
|
230
|
+
|
|
231
|
+
_No host render site found — used by the agent runtime / composed internally._
|
|
232
|
+
|
|
233
|
+
Composed internally by the legacy `ScLogoUnit`:
|
|
234
|
+
|
|
235
|
+
```tsx
|
|
236
|
+
// @streamoid/ui packages/ui/src/SC-Logo unit/ScLogoUnit.tsx:20
|
|
237
|
+
<ScStrLogo type="default" className={styles.scStrLogoInstance} />
|
|
238
|
+
// .scStrLogoInstance forces width: 10.4375rem !important; height: 1rem !important
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
Where it would belong if revived: a full-bleed brand surface (sign-in, splash,
|
|
242
|
+
error page) at ≥200px wide. Every sidebar/header slot in every host app is now
|
|
243
|
+
`ScSideBarLogoUnit` + `ScStreamoidWordmark`/`ScStreamoidMascot`.
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
## Related
|
|
248
|
+
|
|
249
|
+
- `ScStreamoidWordmark` — the current wordmark; `width`/`height`/`color` props, token-masked.
|
|
250
|
+
- `ScStreamoidMascot` — the mascot alone; unique gradient id per instance.
|
|
251
|
+
- `ScSideBarLogoUnit` — the current sidebar header row (takes a `wordmark` node).
|
|
252
|
+
- `ScLogoUnit` — the legacy container that renders this; superseded by `ScSideBarLogoUnit`.
|
|
253
|
+
- `ScAppcardLogos` — per-product wordmarks, when you want the app's name not the company's.
|