@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,256 @@
|
|
|
1
|
+
---
|
|
2
|
+
component: ScValueMappingL1
|
|
3
|
+
package: "@streamoid/ui"
|
|
4
|
+
category: feed-taxonomy
|
|
5
|
+
status: stable
|
|
6
|
+
renders: div
|
|
7
|
+
tags: [value-mapping, curation, attribute-value, list-row, selectable-row, updated-dot, catalogix, map-values]
|
|
8
|
+
related: [ScMappingCard, ScSelectionPillGroup, ScTaxonomyPill, ScDefaultCard]
|
|
9
|
+
do_not_confuse_with: [ScMappingCard, ScSelectionPill, ScDefaultCard, ScTableList]
|
|
10
|
+
used_by: [catalogix]
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# ScValueMappingL1
|
|
14
|
+
|
|
15
|
+
**One selectable row in a value-mapping / curation list.** A full-width rounded box
|
|
16
|
+
containing a single truncating label, three visual states (`default` / `hover` /
|
|
17
|
+
`active`), and an optional blue "this value was edited" dot on the right.
|
|
18
|
+
|
|
19
|
+
## TL;DR for agents
|
|
20
|
+
|
|
21
|
+
- **Reach for it when:** you need a vertical list of *values* (attribute values,
|
|
22
|
+
categories, enum members) where exactly one is the current selection and some
|
|
23
|
+
carry an "updated" marker.
|
|
24
|
+
- **Don't reach for it when:** you're mapping *columns* to attributes with a
|
|
25
|
+
confirm/ignore lifecycle (→ `ScMappingCard`), you want a horizontal segmented
|
|
26
|
+
switch (→ `ScSelectionPillGroup`), or you need a multi-column data row
|
|
27
|
+
(→ `ScTableList` / `ScCatalogixStoreTableList`).
|
|
28
|
+
- **Three things that will bite you:**
|
|
29
|
+
1. `label` defaults to **`"Title"`** — forget it and every row says "Title".
|
|
30
|
+
2. It's a plain `<div>`. `onClick` works because it's spread, but there is **no
|
|
31
|
+
`role`, no `tabIndex`, no keyboard handler**. You add those.
|
|
32
|
+
3. `state` is a *skin*, not selection state. Nothing is tracked; you compute
|
|
33
|
+
`"active"` yourself.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## 1. How to use it
|
|
38
|
+
|
|
39
|
+
### Import
|
|
40
|
+
|
|
41
|
+
```tsx
|
|
42
|
+
import { ScValueMappingL1 } from "@streamoid/ui";
|
|
43
|
+
import "@streamoid/ui/dist/index.css"; // once, at your app root
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Minimal usage
|
|
47
|
+
|
|
48
|
+
```tsx
|
|
49
|
+
<ScValueMappingL1 label="Red" onClick={() => setSelected("Red")} />
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Props
|
|
53
|
+
|
|
54
|
+
| Prop | Type | Default | Notes |
|
|
55
|
+
|---|---|---|---|
|
|
56
|
+
| `label` | `string` | `"Title"` | ⚠️ Has a real default. The whole content of the row. Truncates with ellipsis and gets a native `title` tooltip with the same text. |
|
|
57
|
+
| `state` | `"default"` \| `"hover"` \| `"active"` | `"default"` | Forced visual state. `"active"` = "this is the currently selected row". Real `:hover` also applies the hover skin. |
|
|
58
|
+
| `updated` | `boolean` | `false` | Renders the trailing blue dot **and** adds `padding-right: 0.5rem` to the row. The dot is `aria-hidden`. |
|
|
59
|
+
| `className` | `string` | – | Appended after the internal classes, so it wins on equal specificity. |
|
|
60
|
+
| `...props` | `HTMLAttributes<HTMLDivElement>` | – | `onClick`, `role`, `tabIndex`, `onKeyDown`, `style`, `data-*` all land on the root div. |
|
|
61
|
+
|
|
62
|
+
### What renders in each state
|
|
63
|
+
|
|
64
|
+
| `state` | Background token | Border token |
|
|
65
|
+
|---|---|---|
|
|
66
|
+
| `default` | `--alias-surface-base` | `--alias-border-subtle` |
|
|
67
|
+
| `hover` (or real `:hover`) | `--alias-surface-basesubtle` | `--alias-border-default` |
|
|
68
|
+
| `active` | `--alias-surface-raisedoverlay` | `--alias-border-default` |
|
|
69
|
+
|
|
70
|
+
`active` wins over real `:hover` (its rule is last), so hovering the selected row
|
|
71
|
+
does not flicker back to the hover skin.
|
|
72
|
+
|
|
73
|
+
### Recipes
|
|
74
|
+
|
|
75
|
+
```tsx
|
|
76
|
+
// The standard list: one active row, some rows flagged as edited
|
|
77
|
+
<div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
|
|
78
|
+
{attributeValues.map((attr) => (
|
|
79
|
+
<ScValueMappingL1
|
|
80
|
+
key={attr}
|
|
81
|
+
label={attr}
|
|
82
|
+
state={attr === selectedValue ? "active" : "default"}
|
|
83
|
+
updated={isEdited(attr)}
|
|
84
|
+
onClick={() => setSelectedValue(attr)}
|
|
85
|
+
/>
|
|
86
|
+
))}
|
|
87
|
+
</div>
|
|
88
|
+
|
|
89
|
+
// Make it actually keyboard-operable (the DS does not do this for you)
|
|
90
|
+
<ScValueMappingL1
|
|
91
|
+
label={attr}
|
|
92
|
+
state={attr === selectedValue ? "active" : "default"}
|
|
93
|
+
role="option"
|
|
94
|
+
aria-selected={attr === selectedValue}
|
|
95
|
+
tabIndex={0}
|
|
96
|
+
onClick={() => setSelectedValue(attr)}
|
|
97
|
+
onKeyDown={(e) => {
|
|
98
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
99
|
+
e.preventDefault();
|
|
100
|
+
setSelectedValue(attr);
|
|
101
|
+
}
|
|
102
|
+
}}
|
|
103
|
+
/>
|
|
104
|
+
|
|
105
|
+
// Give the "updated" dot a meaning screen readers can reach
|
|
106
|
+
<ScValueMappingL1 label={attr} updated aria-label={`${attr} (edited)`} />
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## 2. Where to use it
|
|
112
|
+
|
|
113
|
+
- **Catalogix Curation V2 → the attribute-values column.** The left panel lists every
|
|
114
|
+
value of the selected attribute; clicking one loads its curation rules in the right
|
|
115
|
+
panel. This is the component's only production surface today.
|
|
116
|
+
- Any **master/detail list of values** on the feed side: map-values screens,
|
|
117
|
+
synonym lists, enum pickers — a narrow scrolling column of single-line rows next to
|
|
118
|
+
a detail pane.
|
|
119
|
+
- It composes *nothing*. It expects to be stacked directly inside a scrolling flex
|
|
120
|
+
column that supplies the gap.
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## 3. When to use it
|
|
125
|
+
|
|
126
|
+
### Use it when
|
|
127
|
+
|
|
128
|
+
- The list items are **single strings** with no secondary line, no icon, no counts.
|
|
129
|
+
- Exactly **one** row is "current", and the selection drives a neighbouring panel.
|
|
130
|
+
- Some rows need a **subtle "changed since last save" marker** that doesn't steal
|
|
131
|
+
attention (the blue info dot).
|
|
132
|
+
|
|
133
|
+
### Don't use it — reach for this instead
|
|
134
|
+
|
|
135
|
+
| Situation | Use instead |
|
|
136
|
+
|---|---|
|
|
137
|
+
| Mapping a feed **column** to target attributes, with Ignore/Confirm/Edit | `ScMappingCard` |
|
|
138
|
+
| Horizontal segmented switch between 2–5 views | `ScSelectionPillGroup` |
|
|
139
|
+
| A node in a taxonomy tree, with child counts and expand/collapse | `ScTaxonomyPill` |
|
|
140
|
+
| Title + description "pick one of these options" card | `ScDefaultCard` |
|
|
141
|
+
| A row with several aligned columns | `ScTableList`, or `ScCatalogixStoreHeader` + `ScCatalogixStoreTableList` |
|
|
142
|
+
| Multi-select over the list | `ScCheckField` / `ScCheckbox` rows — this row has no checkbox and no multi-select affordance |
|
|
143
|
+
| A real form control whose value gets saved | `ScRadio` / `ScTabField` |
|
|
144
|
+
|
|
145
|
+
### Don't confuse with
|
|
146
|
+
|
|
147
|
+
| You may actually want | Not this |
|
|
148
|
+
|---|---|
|
|
149
|
+
| `ScMappingCard` — column-level card with a `default`/`confirmed`/`ignored` lifecycle, a `targets` slot and an action footer | `ScValueMappingL1` is a single value row with a forced skin and nothing else |
|
|
150
|
+
| `ScSelectionPill` — a *horizontal* pill in a segmented row, real `<button>`, `aria-pressed` | This is a *vertical* full-width row, a `<div>`, no aria |
|
|
151
|
+
| `ScDefaultCard` — generic option card (`title` + optional `description`) | No description line here, and it has an `active` state that `ScDefaultCard` lacks |
|
|
152
|
+
|
|
153
|
+
Both `ScValueMappingL1` and `ScDefaultCard` take a `state` prop with a `"hover"`
|
|
154
|
+
member; only `ScValueMappingL1` has `"active"`. If you need a persistent
|
|
155
|
+
"selected" look, that's the deciding factor.
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## 4. Why to use it
|
|
160
|
+
|
|
161
|
+
- **The three-state token ladder is already correct.** `surface-base` →
|
|
162
|
+
`surface-basesubtle` → `surface-raisedoverlay` stay visually distinct in both
|
|
163
|
+
themes. Hand-rolled selection rows almost always reach for a hard-coded grey that
|
|
164
|
+
collapses to white in light mode and loses the "selected" read entirely.
|
|
165
|
+
- **Truncation with a tooltip, for free.** Long attribute values ellipsise and get a
|
|
166
|
+
`title` fallback, so a 200-character value can't blow out the column width.
|
|
167
|
+
- **The "updated" dot is a token, not a colour.** It uses
|
|
168
|
+
`--alias-text-and-icons-infocont`, matching every other "changed / info" marker
|
|
169
|
+
in the product.
|
|
170
|
+
- **One row height everywhere.** `0.75rem` padding on a `text-sm` line, so the
|
|
171
|
+
Curation list and any future value list line up without per-screen CSS.
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## Gotchas
|
|
176
|
+
|
|
177
|
+
**1. `label` defaults to `"Title"`.** There is no required prop, so a typo'd prop
|
|
178
|
+
name renders a list of "Title".
|
|
179
|
+
|
|
180
|
+
```tsx
|
|
181
|
+
// WRONG — renders "Title" (typo'd prop is silently ignored)
|
|
182
|
+
<ScValueMappingL1 lable={attr} />
|
|
183
|
+
|
|
184
|
+
// RIGHT
|
|
185
|
+
<ScValueMappingL1 label={attr} />
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
**2. No button semantics.** The root is a `<div>` with `cursor: pointer` and nothing
|
|
189
|
+
else — no `role`, no `tabIndex`, no `onKeyDown`, no `aria-selected`. A mouse user
|
|
190
|
+
sees an affordance a keyboard user cannot reach. Pass them yourself (see Recipes).
|
|
191
|
+
|
|
192
|
+
**3. `state` does not track anything.** It is a forced skin. There is no `selected`
|
|
193
|
+
prop and no internal state; if you never compute `"active"`, nothing ever looks
|
|
194
|
+
selected.
|
|
195
|
+
|
|
196
|
+
```tsx
|
|
197
|
+
// WRONG — nothing looks selected, ever
|
|
198
|
+
{values.map((v) => <ScValueMappingL1 key={v} label={v} onClick={() => pick(v)} />)}
|
|
199
|
+
|
|
200
|
+
// RIGHT
|
|
201
|
+
{values.map((v) => (
|
|
202
|
+
<ScValueMappingL1 key={v} label={v} state={v === picked ? "active" : "default"} onClick={() => pick(v)} />
|
|
203
|
+
))}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
**4. `state="hover"` is for design parity, not interaction.** Real `:hover` already
|
|
207
|
+
works. Wiring `onMouseEnter` to flip `state` just fights the CSS.
|
|
208
|
+
|
|
209
|
+
**5. The row supplies no vertical gap.** No margin, no `:not(:last-child)` rule.
|
|
210
|
+
Stacked rows touch unless the parent sets `gap` (Catalogix uses `12px`).
|
|
211
|
+
|
|
212
|
+
**6. It has `width: 100%` but no `flex-shrink: 0`.** Inside a **height-capped** flex
|
|
213
|
+
column the rows compress toward zero height and the list looks empty. Put them in a
|
|
214
|
+
scrolling wrapper instead of a fixed-height column:
|
|
215
|
+
|
|
216
|
+
```css
|
|
217
|
+
/* RIGHT — the host pattern */
|
|
218
|
+
.list-scroll { overflow-y: auto; }
|
|
219
|
+
.list { display: flex; flex-direction: column; gap: 12px; }
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
**7. The `updated` dot carries no accessible name.** It's `aria-hidden` decoration
|
|
223
|
+
occupying `1.5rem`. If "edited" is information the user needs, put it in
|
|
224
|
+
`aria-label` or a visible legend.
|
|
225
|
+
|
|
226
|
+
**8. `updated` changes the row's inner metrics.** It adds `padding-right: 0.5rem`
|
|
227
|
+
plus a `1.5rem` dot slot, so an updated row has a narrower label area than its
|
|
228
|
+
neighbours. Expected, but it means truncation points differ down the list.
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## In the wild
|
|
233
|
+
|
|
234
|
+
```jsx
|
|
235
|
+
// catalogix/dashboard app/containers/StoreSettingsV2/CurationV2/index.jsx:394
|
|
236
|
+
<ScValueMappingL1
|
|
237
|
+
key={idx}
|
|
238
|
+
label={attr}
|
|
239
|
+
state={attr === selectedAttribute ? "active" : "default"}
|
|
240
|
+
updated={isAttrUpdated(attr)}
|
|
241
|
+
onClick={() => setSelectedAttribute(attr)}
|
|
242
|
+
/>
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
Rendered inside `.smp-values { overflow-y: auto }` → `.block { display: flex;
|
|
246
|
+
flex-direction: column; gap: 12px }` — i.e. the host supplies both the scroll
|
|
247
|
+
container and the gap (see Gotchas 5 and 6).
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
## Related
|
|
252
|
+
|
|
253
|
+
- `ScMappingCard` — the column-level sibling on the feed Map-Attributes screen; has the confirm/ignore state machine this row deliberately lacks.
|
|
254
|
+
- `ScSelectionPillGroup` — the horizontal segmented switch that usually sits *above* a `ScValueMappingL1` list (Curation V2 has both).
|
|
255
|
+
- `ScTaxonomyPill` — hierarchy node chip for tree layouts rather than flat lists.
|
|
256
|
+
- `ScDefaultCard` — reach for it when the row needs a description line and no `active` state.
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
---
|
|
2
|
+
component: ScVersion
|
|
3
|
+
package: "@streamoid/ui"
|
|
4
|
+
category: sidebar
|
|
5
|
+
status: legacy
|
|
6
|
+
renders: div
|
|
7
|
+
tags: [sidebar, version, footer, version-stamp, collapse-toggle, legacy, build-number]
|
|
8
|
+
related: [StreamoidSidebar, ScSidebarIcons, ScSidebar, ScMenuOptions]
|
|
9
|
+
do_not_confuse_with: [StreamoidSidebar, ScSidebarIcons, ScMenuOptions, ScBadges]
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# ScVersion
|
|
13
|
+
|
|
14
|
+
**Legacy. Superseded by `StreamoidSidebar`'s `versionText` prop.** The old rail's bottom
|
|
15
|
+
footer: a version string plus a collapse chevron. The chevron is **decorative** (it goes
|
|
16
|
+
through `ScSidebarIcons`, which drops all props), and the version defaults to the
|
|
17
|
+
hardcoded string `"v2.1.2"`.
|
|
18
|
+
|
|
19
|
+
## TL;DR for agents
|
|
20
|
+
|
|
21
|
+
- **Reach for it when:** never. `StreamoidSidebar` renders its own version footer
|
|
22
|
+
inline from `versionText`.
|
|
23
|
+
- **Reach for this instead:** `StreamoidSidebar` with `versionText="v2.1.2"` — or
|
|
24
|
+
`toggleInProfile` if you want the collapse control beside the profile row and no
|
|
25
|
+
version footer at all.
|
|
26
|
+
- **Four things that will bite you:**
|
|
27
|
+
1. ⚠️ `version` defaults to `"v2.1.2"`. Forget it and you ship a stale build number.
|
|
28
|
+
2. `component` and `scSidebarIconsinstance` are **only read in the `collapsed`
|
|
29
|
+
branch**. In `expanded` the component builds its own `SiconCollapse` and ignores
|
|
30
|
+
both props.
|
|
31
|
+
3. The chevron in `expanded` is hardcoded to `state="hover"` — permanently
|
|
32
|
+
hover-skinned.
|
|
33
|
+
4. Nothing inside is clickable. Wire `onClick` on the root (that prop *is* spread) and
|
|
34
|
+
accept that the whole footer becomes the hit area.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## 1. How to use it
|
|
39
|
+
|
|
40
|
+
### Import
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
import { ScVersion } from "@streamoid/ui";
|
|
44
|
+
import { SiconCollapse } from "@streamoid/icons";
|
|
45
|
+
import "@streamoid/ui/dist/index.css"; // once, at your app root
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Minimal usage
|
|
49
|
+
|
|
50
|
+
```tsx
|
|
51
|
+
<ScVersion state="expanded" version={`v${appVersion}`} onClick={toggleSidebar} />
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Props
|
|
55
|
+
|
|
56
|
+
| Prop | Type | Default | Notes |
|
|
57
|
+
|---|---|---|---|
|
|
58
|
+
| `version` | `string` | `"v2.1.2"` | ⚠️ Has a real default — a specific stale version string. Rendered with a **trailing space** (`{version} `). Single line, ellipsised. |
|
|
59
|
+
| `state` | `"expanded"` \| `"collapsed"` | `"expanded"` | Changes both the layout direction and which icon branch runs. See the table below. |
|
|
60
|
+
| `scSidebarIconsinstance` | `JSX.Element` | – | ⚠️ Note the lower-case `i` in `…instance`. The icon handed to the internal `ScSidebarIcons`. **`collapsed` only** — falls back to `<SiconCollapse />`. |
|
|
61
|
+
| `component` | `JSX.Element` | – | Replaces the whole icon slot (wins over `scSidebarIconsinstance`). **`collapsed` only.** |
|
|
62
|
+
| `className` | `string` | – | Concatenated onto the root. ⚠️ Unguarded — omitting it puts a literal `undefined` in the class list. |
|
|
63
|
+
| `...props` | `HTMLAttributes<HTMLDivElement>` | – | **Is** spread onto the root, so `onClick`, `style`, `aria-*`, `data-*` work — on the whole row, not on the chevron. |
|
|
64
|
+
|
|
65
|
+
### What renders in each state
|
|
66
|
+
|
|
67
|
+
| | `expanded` | `collapsed` |
|
|
68
|
+
|---|---|---|
|
|
69
|
+
| Direction | `row`, 4 px gap, padding `4px 4px 4px 16px` | `column`, 12 px gap, padding `16px 8px`, fixed `width: 3.5rem` |
|
|
70
|
+
| Order | `version` (flex: 1) → chevron | chevron → `version` |
|
|
71
|
+
| Icon source | **hardcoded** `<SiconCollapse />` inside `ScSidebarIcons state="hover"`. `component` and `scSidebarIconsinstance` are **ignored**. | `component` ?? `ScSidebarIcons instance={scSidebarIconsinstance ?? <SiconCollapse />}` |
|
|
72
|
+
| Type ramp | `text-sm-regular`, left-aligned | `text-xs-regular`, centred |
|
|
73
|
+
| Colour | `--alias-text-and-icons-muted` | same |
|
|
74
|
+
|
|
75
|
+
### Recipes
|
|
76
|
+
|
|
77
|
+
```tsx
|
|
78
|
+
// Collapsed footer with your own icon (the only state where the icon props work)
|
|
79
|
+
<ScVersion
|
|
80
|
+
state="collapsed"
|
|
81
|
+
version={`v${appVersion}`}
|
|
82
|
+
scSidebarIconsinstance={<SiconCollapse size={20} />}
|
|
83
|
+
onClick={toggleSidebar}
|
|
84
|
+
/>
|
|
85
|
+
|
|
86
|
+
// Collapsed footer, replacing the entire icon slot
|
|
87
|
+
<ScVersion
|
|
88
|
+
state="collapsed"
|
|
89
|
+
version={`v${appVersion}`}
|
|
90
|
+
component={<MyOwnToggleButton onClick={toggleSidebar} />}
|
|
91
|
+
/>
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
The replacement, which is what you should actually write:
|
|
95
|
+
|
|
96
|
+
```tsx
|
|
97
|
+
// Version footer + a working collapse toggle, rendered by the shell
|
|
98
|
+
<StreamoidSidebar
|
|
99
|
+
expanded={expanded}
|
|
100
|
+
onToggle={() => setExpanded((v) => !v)}
|
|
101
|
+
config={config}
|
|
102
|
+
iconMap={iconMap}
|
|
103
|
+
versionText={`v${appVersion}`} // default is "v1.0.0"
|
|
104
|
+
toggleIcon={(isExpanded) => <SiconCollapse size={20} />}
|
|
105
|
+
/>
|
|
106
|
+
|
|
107
|
+
// Or: no version footer at all — profile row + a separate collapse button beside it
|
|
108
|
+
<StreamoidSidebar … versionText={undefined} toggleInProfile />
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## 2. Where to use it
|
|
114
|
+
|
|
115
|
+
Nowhere. Its only render site is the legacy `ScSidebar`
|
|
116
|
+
(`src/SC-Sidebar/ScSidebar.tsx:140` collapsed, `:248` expanded), which is itself unused.
|
|
117
|
+
|
|
118
|
+
`StreamoidSidebar` renders the version footer **inline** — it does not compose
|
|
119
|
+
`ScVersion` — from `versionText` (default `"v1.0.0"`), and owns the collapse toggle via
|
|
120
|
+
`onToggle` / `toggleIcon` / `toggleInProfile`.
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## 3. When to use it
|
|
125
|
+
|
|
126
|
+
### Use it when
|
|
127
|
+
|
|
128
|
+
- Never.
|
|
129
|
+
|
|
130
|
+
### Don't use it — reach for this instead
|
|
131
|
+
|
|
132
|
+
| Situation | Use instead |
|
|
133
|
+
|---|---|
|
|
134
|
+
| A version stamp in a real sidebar footer | `StreamoidSidebar`'s `versionText` |
|
|
135
|
+
| A working collapse/expand control | `StreamoidSidebar`'s `onToggle` + `toggleIcon`, or `toggleInProfile` |
|
|
136
|
+
| A version line inside a profile/settings popup menu row | `ScMenuOptions` (`variant="with-v"`, `version` prop) |
|
|
137
|
+
| A version pill/chip somewhere in the UI | `ScBadges` (`text`, `variant`, `styleVariant`) |
|
|
138
|
+
| Any clickable icon | `ScButton styleVariant="icon-only"` |
|
|
139
|
+
|
|
140
|
+
### Don't confuse with
|
|
141
|
+
|
|
142
|
+
| You may actually want | Not this |
|
|
143
|
+
|---|---|
|
|
144
|
+
| `StreamoidSidebar`'s `versionText` — the current, working footer | `ScVersion` is the standalone legacy footer |
|
|
145
|
+
| `ScMenuOptions` with `variant="with-v"` — a **popup menu row** that also shows a version | not a sidebar footer |
|
|
146
|
+
| `ScBadges` — a small status/count chip | `ScVersion` is a full-width footer row |
|
|
147
|
+
| `ScSidebarIcons` — the inert icon box this component wraps | also legacy |
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## 4. Why to use it
|
|
152
|
+
|
|
153
|
+
You wouldn't. What it still encodes correctly:
|
|
154
|
+
|
|
155
|
+
- The version stamp is `--alias-text-and-icons-muted` — the dimmest text token, so a
|
|
156
|
+
build number never competes with nav labels.
|
|
157
|
+
- Expanded uses `text-sm` left-aligned with the chevron pushed right by `flex: 1`;
|
|
158
|
+
collapsed drops to `text-xs`, centres, and stacks the chevron above the string. Both
|
|
159
|
+
are the correct Figma treatments.
|
|
160
|
+
- `text-overflow: ellipsis` on the version, so a long build hash truncates rather than
|
|
161
|
+
widening the rail.
|
|
162
|
+
|
|
163
|
+
What you lose: a working toggle, and any way to change the icon in the expanded state.
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Gotchas
|
|
168
|
+
|
|
169
|
+
**1. `version` defaults to `"v2.1.2"`.** Not a placeholder like "Version" — an actual
|
|
170
|
+
version number that will look plausible and be wrong.
|
|
171
|
+
|
|
172
|
+
```tsx
|
|
173
|
+
// WRONG — ships "v2.1.2"
|
|
174
|
+
<ScVersion state="expanded" />
|
|
175
|
+
|
|
176
|
+
// RIGHT
|
|
177
|
+
<ScVersion state="expanded" version={`v${appVersion}`} />
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
**2. `component` and `scSidebarIconsinstance` are ignored when expanded.** The expanded
|
|
181
|
+
branch constructs its own `<ScSidebarIcons instance={<SiconCollapse />} state="hover" />`
|
|
182
|
+
and never consults either prop. The legacy `ScSidebar` passes both anyway — don't take
|
|
183
|
+
that call site as an example.
|
|
184
|
+
|
|
185
|
+
```tsx
|
|
186
|
+
// WRONG — your icon never appears
|
|
187
|
+
<ScVersion state="expanded" scSidebarIconsinstance={<SiconUp />} />
|
|
188
|
+
|
|
189
|
+
// RIGHT — the icon props only work collapsed
|
|
190
|
+
<ScVersion state="collapsed" scSidebarIconsinstance={<SiconUp />} />
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
**3. The chevron is not a button.** It renders through `ScSidebarIcons`, which
|
|
194
|
+
destructures `...props` and never spreads it, so there is no way to attach a handler to
|
|
195
|
+
the icon. `ScVersion`'s own `...props` *is* spread on the root, so an `onClick` there
|
|
196
|
+
makes the **whole footer row** the hit area — including the version text.
|
|
197
|
+
|
|
198
|
+
**4. `state="hover"` is baked into the expanded chevron.** It permanently renders the
|
|
199
|
+
hover background. There is no prop to turn it off.
|
|
200
|
+
|
|
201
|
+
**5. The prop name is `scSidebarIconsinstance`.** Lower-case `i` on `instance`, mixed
|
|
202
|
+
into a camel-cased component name. It's a Figma-export artifact and an easy typo — and
|
|
203
|
+
a typo is silent, because every prop is optional.
|
|
204
|
+
|
|
205
|
+
**6. Fixed `width: 3.5rem` when collapsed.** 56 px, wider than the 40 px collapsed nav
|
|
206
|
+
squares and the 48 px collapsed profile box, so the footer sets the rail's minimum
|
|
207
|
+
width.
|
|
208
|
+
|
|
209
|
+
**7. `version` renders with a trailing space.** The JSX is `{version} ` — visible in DOM
|
|
210
|
+
snapshots and in text assertions.
|
|
211
|
+
|
|
212
|
+
**8. `className` produces a literal `undefined` class when omitted.**
|
|
213
|
+
`styles.scVersion + " " + className + " " + variantsClassName`.
|
|
214
|
+
|
|
215
|
+
**9. No `role`, `tabIndex` or keyboard handling.** If you make the row clickable via
|
|
216
|
+
`onClick`, supply those yourself through `...props`.
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## In the wild
|
|
221
|
+
|
|
222
|
+
_No host render site found — used by the agent runtime / composed internally._
|
|
223
|
+
|
|
224
|
+
Composed only inside the legacy sidebar:
|
|
225
|
+
|
|
226
|
+
```tsx
|
|
227
|
+
// npm-components packages/ui/src/SC-Sidebar/ScSidebar.tsx:140
|
|
228
|
+
<ScVersion
|
|
229
|
+
state="collapsed"
|
|
230
|
+
scSidebarIconsinstance={
|
|
231
|
+
<SiconCollapse className={styles.siconCollapseInstance} />
|
|
232
|
+
}
|
|
233
|
+
className={styles.scVersionInstance}
|
|
234
|
+
/>
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
Where it *would* belong — the rail's bottom footer — is now rendered inline by
|
|
238
|
+
`StreamoidSidebar` from `versionText`
|
|
239
|
+
(`packages/ui/src/SC-Sidebar-new/streamoid-sidebar.tsx:787`), which every host drives
|
|
240
|
+
(e.g. `cxo-dashboard src/app/components/app-sidebar.tsx`).
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## Related
|
|
245
|
+
|
|
246
|
+
- `StreamoidSidebar` — **the replacement.** `versionText` for the stamp, `onToggle` /
|
|
247
|
+
`toggleIcon` / `toggleInProfile` for the collapse control.
|
|
248
|
+
- `ScSidebarIcons` — the inert icon box this composes; also legacy.
|
|
249
|
+
- `ScMenuOptions` — popup menu row with a `version` slot (`variant="with-v"`).
|
|
250
|
+
- `ScSidebar` / `ScLogoUnit` / `ScSidebarProfile` — the rest of this legacy sidebar
|
|
251
|
+
family.
|