@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.
Files changed (131) hide show
  1. package/README.md +35 -18
  2. package/dist/docs/AGENTS.md +321 -0
  3. package/dist/docs/CreditWarningBanner.md +305 -0
  4. package/dist/docs/InvoiceHistoryMobile.md +222 -0
  5. package/dist/docs/ScAccess.md +259 -0
  6. package/dist/docs/ScAppCard.md +244 -0
  7. package/dist/docs/ScAppCardForCopilot.md +230 -0
  8. package/dist/docs/ScAppCardV3.md +273 -0
  9. package/dist/docs/ScAppField.md +308 -0
  10. package/dist/docs/ScAppListingCard.md +271 -0
  11. package/dist/docs/ScAppSwitchPanel.md +286 -0
  12. package/dist/docs/ScAppcardLogos.md +226 -0
  13. package/dist/docs/ScArtifaxInvite.md +262 -0
  14. package/dist/docs/ScArtifaxSidebar.md +330 -0
  15. package/dist/docs/ScAskAgentButton.md +307 -0
  16. package/dist/docs/ScBadges.md +261 -0
  17. package/dist/docs/ScBeacon.md +244 -0
  18. package/dist/docs/ScBillingHistoryHeader.md +210 -0
  19. package/dist/docs/ScBillingHistoryTableList.md +243 -0
  20. package/dist/docs/ScBillingLogsTableHeader.md +212 -0
  21. package/dist/docs/ScBillingLogsTableList.md +251 -0
  22. package/dist/docs/ScBriefCard.md +255 -0
  23. package/dist/docs/ScButton.md +251 -0
  24. package/dist/docs/ScCalendar.md +268 -0
  25. package/dist/docs/ScCalendarDateComps.md +264 -0
  26. package/dist/docs/ScCatalogixInvite.md +345 -0
  27. package/dist/docs/ScCatalogixSidebar.md +337 -0
  28. package/dist/docs/ScCatalogixStoreHeader.md +246 -0
  29. package/dist/docs/ScCatalogixStoreTableList.md +316 -0
  30. package/dist/docs/ScCheckField.md +233 -0
  31. package/dist/docs/ScCheckbox.md +272 -0
  32. package/dist/docs/ScCounter.md +235 -0
  33. package/dist/docs/ScCreditsUsageCard.md +247 -0
  34. package/dist/docs/ScCreditsUsageCardMobile.md +224 -0
  35. package/dist/docs/ScDefaultCard.md +269 -0
  36. package/dist/docs/ScDp.md +245 -0
  37. package/dist/docs/ScDrawer.md +318 -0
  38. package/dist/docs/ScFieldButton.md +255 -0
  39. package/dist/docs/ScFileField.md +268 -0
  40. package/dist/docs/ScGoogleSignIn.md +250 -0
  41. package/dist/docs/ScGuide.md +278 -0
  42. package/dist/docs/ScHDivider.md +213 -0
  43. package/dist/docs/ScHeader.md +222 -0
  44. package/dist/docs/ScImageField.md +253 -0
  45. package/dist/docs/ScInChatList.md +277 -0
  46. package/dist/docs/ScInChatMessage.md +205 -0
  47. package/dist/docs/ScInfoPopup.md +248 -0
  48. package/dist/docs/ScIntialProfileCover.md +233 -0
  49. package/dist/docs/ScInvoiceHistoryMobile.md +187 -0
  50. package/dist/docs/ScLogoUnit.md +232 -0
  51. package/dist/docs/ScMappingCard.md +241 -0
  52. package/dist/docs/ScMediaApproval.md +301 -0
  53. package/dist/docs/ScMediaSelect.md +310 -0
  54. package/dist/docs/ScMenuOptions.md +308 -0
  55. package/dist/docs/ScMobileBottomAction.md +252 -0
  56. package/dist/docs/ScMobileTopNav.md +279 -0
  57. package/dist/docs/ScModal.md +291 -0
  58. package/dist/docs/ScOnlyField.md +302 -0
  59. package/dist/docs/ScOnlyIcon.md +213 -0
  60. package/dist/docs/ScPagination.md +284 -0
  61. package/dist/docs/ScPairtext.md +287 -0
  62. package/dist/docs/ScPendingAction.md +238 -0
  63. package/dist/docs/ScPhtogenixInvite.md +275 -0
  64. package/dist/docs/ScPlanCard.md +302 -0
  65. package/dist/docs/ScPlanComparison.md +264 -0
  66. package/dist/docs/ScPlanDetailsCard.md +246 -0
  67. package/dist/docs/ScPlanDetailsCardMobile.md +240 -0
  68. package/dist/docs/ScPopUpMenu.md +224 -0
  69. package/dist/docs/ScProfile.md +234 -0
  70. package/dist/docs/ScProfileImageUpdate.md +261 -0
  71. package/dist/docs/ScProfileOptions.md +245 -0
  72. package/dist/docs/ScProfilePopup.md +396 -0
  73. package/dist/docs/ScProfileSettingsComp.md +250 -0
  74. package/dist/docs/ScProfileV2Mobile.md +216 -0
  75. package/dist/docs/ScProgressBar.md +267 -0
  76. package/dist/docs/ScQuickPrompt.md +277 -0
  77. package/dist/docs/ScRadio.md +228 -0
  78. package/dist/docs/ScReferralCardMobile.md +226 -0
  79. package/dist/docs/ScReferralTableHeader.md +260 -0
  80. package/dist/docs/ScReferralTableList.md +293 -0
  81. package/dist/docs/ScRole.md +226 -0
  82. package/dist/docs/ScRoleMobile.md +199 -0
  83. package/dist/docs/ScSelect.md +270 -0
  84. package/dist/docs/ScSelection.md +256 -0
  85. package/dist/docs/ScSelectionList.md +272 -0
  86. package/dist/docs/ScSelectionPill.md +240 -0
  87. package/dist/docs/ScSelectionPillGroup.md +302 -0
  88. package/dist/docs/ScSettingsNav.md +212 -0
  89. package/dist/docs/ScSettingsTabComp.md +260 -0
  90. package/dist/docs/ScSideBarLogoUnit.md +340 -0
  91. package/dist/docs/ScSidebar.md +243 -0
  92. package/dist/docs/ScSidebarIcons.md +232 -0
  93. package/dist/docs/ScSidebarMenu.md +283 -0
  94. package/dist/docs/ScSidebarProfile.md +231 -0
  95. package/dist/docs/ScSidebarSwitchMenu.md +258 -0
  96. package/dist/docs/ScSlider.md +194 -0
  97. package/dist/docs/ScStoreCard.md +252 -0
  98. package/dist/docs/ScStrLogo.md +253 -0
  99. package/dist/docs/ScStreamoidWordmark.md +302 -0
  100. package/dist/docs/ScSubAgent.md +226 -0
  101. package/dist/docs/ScTabComp.md +308 -0
  102. package/dist/docs/ScTabField.md +258 -0
  103. package/dist/docs/ScTabSwitcher.md +307 -0
  104. package/dist/docs/ScTableHeader.md +261 -0
  105. package/dist/docs/ScTableList.md +301 -0
  106. package/dist/docs/ScTableListMobile.md +282 -0
  107. package/dist/docs/ScTabs.md +268 -0
  108. package/dist/docs/ScTaxonomyPill.md +263 -0
  109. package/dist/docs/ScTextArea.md +259 -0
  110. package/dist/docs/ScTextField.md +324 -0
  111. package/dist/docs/ScThinkingStepIcon.md +249 -0
  112. package/dist/docs/ScTodoList.md +288 -0
  113. package/dist/docs/ScToggleSwitch.md +229 -0
  114. package/dist/docs/ScUsageHistoryMobile.md +194 -0
  115. package/dist/docs/ScVDivider.md +215 -0
  116. package/dist/docs/ScValueMappingL1.md +256 -0
  117. package/dist/docs/ScVersion.md +251 -0
  118. package/dist/docs/ScWorkspace.md +233 -0
  119. package/dist/docs/ScWorkspaceCard.md +234 -0
  120. package/dist/docs/ScWorkspaceSettingsMobile.md +265 -0
  121. package/dist/docs/ScWorkspaceSwitchCard.md +314 -0
  122. package/dist/docs/ScWorkspaceSwitchMobile.md +241 -0
  123. package/dist/docs/ScWorkspaceSwitchMobileV2.md +278 -0
  124. package/dist/docs/StreamoidSidebar.md +403 -0
  125. package/dist/docs/StreamoidWorkspaceSwitcher.md +307 -0
  126. package/dist/docs/UsageHistoryMobile.md +235 -0
  127. package/dist/docs/components.json +4849 -0
  128. package/dist/index.css +36 -36
  129. package/dist/index.d.mts +10 -0
  130. package/dist/index.d.ts +10 -0
  131. package/package.json +3 -2
@@ -0,0 +1,224 @@
1
+ ---
2
+ component: ScPopUpMenu
3
+ package: "@streamoid/ui"
4
+ category: overlays
5
+ status: legacy
6
+ tags: [menu, menu-row, popup, kebab, context-menu, option, legacy]
7
+ renders: div
8
+ related: [ScMenuOptions, ScProfilePopup, ScProfileOptions, ScModal]
9
+ do_not_confuse_with: [ScMenuOptions, ScProfilePopup, ScModal, ScInfoPopup]
10
+ ---
11
+
12
+ # ScPopUpMenu
13
+
14
+ **A single 242px-wide menu *row* — despite the name, not a popup and not a menu.**
15
+ It renders one `<div>` with an optional icon and a label, plus a `state="clicked"`
16
+ background flag. It creates no overlay, no list, no positioning and no dismissal.
17
+
18
+ > **status: legacy.** `ScMenuOptions` is the row every app actually renders (CXO,
19
+ > Photogenix, Artifax, and `ScProfilePopup`/`ScProfileOptions` internally), and it
20
+ > has hover states, an `error` variant, a version slot and a props spread that this
21
+ > one lacks. `ScPopUpMenu` has **no call site anywhere** — host repos or DS
22
+ > internals. **Use `ScMenuOptions`.** It is documented here only so an agent that
23
+ > greps the name is redirected instead of adopting it.
24
+
25
+ ## TL;DR for agents
26
+
27
+ - **Reach for it when:** never, in new code.
28
+ - **Reach for this instead:** `ScMenuOptions` for the row, `ScProfilePopup` /
29
+ `ScProfileOptions` for the panel that contains the rows, `ScModal` / `ScDrawer`
30
+ if you actually wanted an overlay.
31
+ - **Three things that will bite you:**
32
+ 1. The name promises a popover. There is none — this is one row of chrome.
33
+ 2. The label prop is `menu`, not `text` or `label`, and it defaults to
34
+ `"Options"` ⚠️.
35
+ 3. There is **no `:hover` rule in its CSS at all.** The row gives zero pointer
36
+ feedback unless you drive `state="clicked"` yourself.
37
+
38
+ ---
39
+
40
+ ## 1. How to use it
41
+
42
+ ### Import
43
+
44
+ ```tsx
45
+ import { ScPopUpMenu } from "@streamoid/ui";
46
+ import "@streamoid/ui/dist/index.css"; // once, at your app root
47
+ ```
48
+
49
+ ### Minimal usage
50
+
51
+ ```tsx
52
+ <ScPopUpMenu menu="Duplicate" icon={<SiconCopy size={24} />} onClick={duplicate} />
53
+ ```
54
+
55
+ The `ScMenuOptions` equivalent, which is what you should ship:
56
+
57
+ ```tsx
58
+ <ScMenuOptions
59
+ text="Duplicate"
60
+ icon={<SiconCopy size={24} />}
61
+ variant="default"
62
+ style={{ width: "100%", cursor: "pointer" }}
63
+ role="button"
64
+ tabIndex={0}
65
+ onClick={duplicate}
66
+ />
67
+ ```
68
+
69
+ ### Props
70
+
71
+ | Prop | Type | Default | Notes |
72
+ |---|---|---|---|
73
+ | `menu` | `string` | `"Options"` | ⚠️ The label — note the prop name, and the real default. `ScMenuOptions` calls the same thing `text`. |
74
+ | `state` | `"default"` \| `"clicked"` | `"default"` | `"clicked"` paints `--alias-surface-canvas` behind the row. Purely a style flag — the component never sets it itself. |
75
+ | `icon` | `JSX.Element` | – | No default (unlike `ScMenuOptions`, which defaults to `SiconTeam`). Rendered in a 24×24 `flex-shrink: 0` box **only when truthy** — no reserved gutter when absent. |
76
+ | `onClick` | `(e: React.MouseEvent) => void` | – | Plain click on the root `<div>`. |
77
+ | `className` | `string` | – | Concatenated unconditionally — see Gotcha 4. |
78
+ | `...props` | `HTMLAttributes<HTMLDivElement>` | – | Spread onto the root div (`style`, `role`, `tabIndex`, `data-*`, `aria-*`, `onKeyDown`). |
79
+
80
+ ### What it actually renders
81
+
82
+ ```html
83
+ <div class="scPopUpMenu state-default {className}">
84
+ <!-- width:242px · display:flex · gap:12px · padding:12px 4px · radius:8px · cursor:pointer -->
85
+ <span class="icon">{icon}</span> <!-- only when icon is truthy; 24×24 -->
86
+ <p class="menuText">{menu}</p> <!-- 16px/24 medium; --alias-text-and-icons-secondary; nowrap -->
87
+ </div>
88
+ ```
89
+
90
+ ---
91
+
92
+ ## 2. Where to use it
93
+
94
+ Nowhere new. The surfaces it was drawn for are all served by other parts:
95
+
96
+ | Surface | What actually ships there |
97
+ |---|---|
98
+ | Profile / account flyout rows | `ScMenuOptions` inside `ScProfilePopup` (CXO `profile-popup.tsx`, Artifax `DashboardSidebar.tsx`) |
99
+ | Sidebar settings rows (Teams / Billing / Settings / What's new) | `ScMenuOptions` (`variant="with-v"` for the version row) |
100
+ | Kebab / row-overflow menus | `ScMenuOptions` in an app-positioned container (Photogenix `studio/BatchList.tsx`) |
101
+ | The container/overlay itself | `ScProfilePopup` (panel body), or `ScModal` / `ScDrawer` |
102
+
103
+ ---
104
+
105
+ ## 3. When to use it
106
+
107
+ ### Use it when
108
+
109
+ - Never in new code. If you are maintaining something that already imports it,
110
+ migrating to `ScMenuOptions` is a rename of `menu` → `text` plus dropping
111
+ `state` (real `:hover` replaces it).
112
+
113
+ ### Don't use it — reach for this instead
114
+
115
+ | Situation | Use instead |
116
+ |---|---|
117
+ | A row in any menu, flyout or sidebar list | `ScMenuOptions` |
118
+ | The profile/account flyout panel itself | `ScProfilePopup` (body only) or `ScProfileOptions` |
119
+ | An actual popover/overlay container | `ScModal` (centered) or `ScDrawer` (edge) |
120
+ | A contextual help bubble | `ScInfoPopup` — the only thing here that really pops up |
121
+ | A destructive row ("Delete", "Log out") | `ScMenuOptions variant="error"` (this component has no error variant) |
122
+ | A row that needs a trailing version/meta string | `ScMenuOptions variant="with-v"` + `version` |
123
+ | A button | `ScButton` |
124
+
125
+ ### Don't confuse with
126
+
127
+ | You may actually want | Not this |
128
+ |---|---|
129
+ | `ScMenuOptions` — the current menu row: hover fills, `error` variant, `with-v` version slot, 200px wide, `text` prop | `ScPopUpMenu` — 242px, no hover, no variants, `menu` prop |
130
+ | `ScProfilePopup` — the panel that holds menu rows | `ScPopUpMenu` holds nothing |
131
+ | `ScInfoPopup` — an actual click-to-open popover | `ScPopUpMenu` never opens anything |
132
+ | `ScModal` / `ScDrawer` — the overlay primitives | `ScPopUpMenu` renders no overlay |
133
+
134
+ ---
135
+
136
+ ## 4. Why to use it
137
+
138
+ You shouldn't. What you'd be giving up by picking it over `ScMenuOptions`:
139
+
140
+ - **Hover feedback.** `ScMenuOptions` has real `:hover` fills
141
+ (`--alias-fill-neutral-neutralhover`, and `--alias-fill-error-secondary` for the
142
+ error variant). `ScPopUpMenu.module.css` contains no `:hover` rule, so the row is
143
+ inert under the pointer.
144
+ - **Semantic variants.** No `error` colouring, no version/meta slot.
145
+ - **Truncation.** `ScMenuOptions`'s label is `flex: 1` with
146
+ `text-overflow: ellipsis`; this one is `white-space: nowrap` with no ellipsis and
147
+ no flex, so a long label overflows the fixed 242px box.
148
+ - **Battle-tested defaults.** Every app already passes the same
149
+ `style={{ width: "100%", cursor: "pointer" }}` to `ScMenuOptions`; that idiom, and
150
+ the Enter/Space `onKeyDown` helper in `ScProfilePopup`, exist for the row that is
151
+ actually in use.
152
+
153
+ Both use `--alias-*` tokens, so theme correctness is not the differentiator — reach
154
+ is.
155
+
156
+ ---
157
+
158
+ ## Gotchas
159
+
160
+ **1. The name is wrong.** It is a row, not a popup and not a menu. It has no
161
+ `open`, no anchor, no portal, no outside-click. If you were looking for the thing
162
+ that pops up, you want `ScProfilePopup` (panel), `ScModal` / `ScDrawer` (overlay),
163
+ or `ScInfoPopup` (bubble).
164
+
165
+ **2. `menu` defaults to `"Options"`.** Forget the prop — or reach for `text` out of
166
+ `ScMenuOptions` habit — and the row silently reads "Options".
167
+
168
+ ```tsx
169
+ // WRONG — `text` is not a prop here; renders "Options"
170
+ <ScPopUpMenu text="Duplicate" />
171
+
172
+ // RIGHT (but prefer ScMenuOptions)
173
+ <ScPopUpMenu menu="Duplicate" />
174
+ ```
175
+
176
+ **3. No hover styling exists.** `.state-default` is `background: transparent` and
177
+ there is no `:hover` selector, so `state="clicked"` is the only way to show any
178
+ fill — and you have to drive it from your own state.
179
+
180
+ **4. `className` is concatenated unconditionally.** The class attribute becomes
181
+ `scPopUpMenu state-default undefined` when you omit it. Harmless in the browser,
182
+ but it shows up in the DOM and breaks exact-match snapshot tests.
183
+
184
+ **5. Fixed `width: 242px`.** Not responsive, and different from `ScMenuOptions`'
185
+ 200px — mixing the two in one list gives you two row widths. Override via `style`.
186
+
187
+ **6. Asymmetric padding: `12px 4px`.** 12px vertical, 4px horizontal, so any
188
+ background you paint via `state="clicked"` hugs the text almost edge-to-edge.
189
+
190
+ **7. `icon` has no reserved gutter.** When `icon` is falsy the 24px box is not
191
+ rendered at all, so labels in a mixed list of rows with and without icons do not
192
+ line up. Pass a spacer element if you need alignment.
193
+
194
+ **8. Plain `<div>` with `onClick` — no a11y.** No `role`, no `tabIndex`, no
195
+ keyboard activation. Add `role="menuitem" tabIndex={0}` plus an Enter/Space
196
+ `onKeyDown` via the spread (this is exactly what `ScProfilePopup` does for its
197
+ `ScMenuOptions` rows).
198
+
199
+ **9. `icon` is rendered raw.** No `cloneElement`, no size normalisation, no
200
+ `currentColor` — unlike `ScButton`, your icon keeps its own size and colour, and it
201
+ will not track the label's `--alias-text-and-icons-secondary`.
202
+
203
+ ---
204
+
205
+ ## In the wild
206
+
207
+ _No host render site found — used by the agent runtime / composed internally._
208
+
209
+ To be precise: it is used by **nothing** — not the four host dashboards, not the
210
+ chat/agent runtime, and not any other component in `packages/ui`. Every surface it
211
+ looks like it belongs to (profile flyout rows, sidebar settings rows, kebab menus)
212
+ already ships `ScMenuOptions` instead — see
213
+ `cxo-dashboard/src/app/components/profile-popup.tsx:298` and
214
+ `artifax/packages/shared/src/components/DashboardSidebar.tsx:927`.
215
+
216
+ ---
217
+
218
+ ## Related
219
+
220
+ - `ScMenuOptions` — **the replacement.** Same job, hover states, `error`/`with-v` variants, and it is what all four apps render.
221
+ - `ScProfilePopup` — the profile flyout panel body that hosts menu rows.
222
+ - `ScProfileOptions` — the older profile-options block, also built from `ScMenuOptions`.
223
+ - `ScModal` / `ScDrawer` — the real overlay primitives.
224
+ - `ScInfoPopup` — the only component in this category that actually opens a popover.
@@ -0,0 +1,234 @@
1
+ ---
2
+ component: ScProfile
3
+ package: "@streamoid/ui"
4
+ category: profile
5
+ status: stable
6
+ renders: div
7
+ tags: [profile, identity, avatar-with-name, name-subtext, sidebar-footer, user-row]
8
+ related: [ScWorkspace, ScProfilePopup, ScDp, ScProfileV2Mobile, ScSidebarProfile]
9
+ do_not_confuse_with: [ScWorkspace, ScProfileOptions, ScProfilePopup, ScProfileSettingsComp, ScProfileV2Mobile]
10
+ ---
11
+
12
+ # ScProfile
13
+
14
+ **The person identity row: circular avatar + name + one grey sub-line.** 200px wide,
15
+ two ellipsised text lines, and a `collapsed` variant that drops the text and shrinks
16
+ the avatar to 32px. It is a presentation row — it owns no menu, no click behaviour
17
+ and no state.
18
+
19
+ ## TL;DR for agents
20
+
21
+ - **Reach for it when:** you need "avatar, name, second line" as one unit inside a
22
+ DS composite you are building.
23
+ - **Don't reach for it when:** you want the whole profile menu (→ `ScProfilePopup`),
24
+ a **workspace** identity row (→ `ScWorkspace`), the mobile profile block
25
+ (→ `ScProfileV2Mobile`), or just the avatar (→ `ScDp`).
26
+ - **Four things that will bite you:**
27
+ 1. `profileImage` defaults to the literal string **`"profile-image0.png"`** — a
28
+ relative path that 404s and renders a broken-image glyph. There is no initials
29
+ fallback anywhere in this component.
30
+ 2. `collapsed` is the **string** `"false" | "true"`, not a boolean.
31
+ 3. Defaults are placeholder identity: **"Chris Hemsworth" / "Kepler workspace"**.
32
+ 4. `className` is concatenated unconditionally, so omitting it puts the literal
33
+ class `undefined` on the root. Harmless, but it shows up in snapshots.
34
+
35
+ ---
36
+
37
+ ## 1. How to use it
38
+
39
+ ### Import
40
+
41
+ ```tsx
42
+ import { ScProfile } from "@streamoid/ui";
43
+ import "@streamoid/ui/dist/index.css"; // once, at your app root
44
+ ```
45
+
46
+ ### Minimal usage
47
+
48
+ ```tsx
49
+ <ScProfile name={user.name} subText={user.email} profileImage={user.avatarUrl} />
50
+ ```
51
+
52
+ ### Props
53
+
54
+ | Prop | Type | Default | Notes |
55
+ |---|---|---|---|
56
+ | `name` | `string` | `"Chris Hemsworth"` | ⚠️ Real default. First line, `text-sm/medium`, single line + ellipsis. |
57
+ | `subText` | `string` | `"Kepler workspace"` | ⚠️ Real default. Second line, `text-xs/regular`, tertiary colour. `ScProfilePopup` feeds the **email** here. |
58
+ | `collapsed` | `"false"` \| `"true"` | `"false"` | ⚠️ A **string** union, not a boolean. `"true"` hides both text lines and shrinks the avatar 40px → 32px. |
59
+ | `profileImage` | `string` | `"profile-image0.png"` | ⚠️ Real default that resolves relative to the page and 404s. Always pass a real URL. |
60
+ | `className` | `string` | – | Appended (see Gotcha 4). |
61
+ | `...props` | `HTMLAttributes<HTMLDivElement>` | – | `onClick`, `style`, `aria-*`, `data-*` are spread onto the root div — but you get **no** button semantics. |
62
+
63
+ ### What renders in each `collapsed` value
64
+
65
+ | Region | `"false"` | `"true"` |
66
+ |---|---|---|
67
+ | Root width | fixed `12.5rem` (200px) | `width: unset` — shrinks to the avatar |
68
+ | Avatar | 2.5rem circle | 2rem circle |
69
+ | `name` / `subText` | rendered | **not rendered at all** |
70
+
71
+ ### Recipes
72
+
73
+ ```tsx
74
+ // Sidebar footer identity, driven by the shell's collapse state
75
+ <ScProfile
76
+ name={user.name}
77
+ subText={user.email}
78
+ profileImage={user.avatarUrl ?? FALLBACK_AVATAR_URL}
79
+ collapsed={sidebarCollapsed ? "true" : "false"}
80
+ />
81
+
82
+ // Full-width inside a flex column (it is 200px by default — override to stretch)
83
+ <ScProfile
84
+ name={member.name}
85
+ subText={member.email}
86
+ profileImage={member.avatarUrl}
87
+ style={{ flex: 1, width: "auto", minWidth: 0 }}
88
+ />
89
+
90
+ // Interactive: give it real semantics yourself
91
+ <button type="button" onClick={openMenu} style={{ all: "unset", cursor: "pointer" }}>
92
+ <ScProfile name={user.name} subText={user.email} profileImage={user.avatarUrl} />
93
+ </button>
94
+ ```
95
+
96
+ ---
97
+
98
+ ## 2. Where to use it
99
+
100
+ Almost always **inside** another DS component rather than directly in a host screen.
101
+ It is composed by:
102
+
103
+ | Parent | Role |
104
+ |---|---|
105
+ | `ScProfilePopup` | the panel header identity (name + email), avatar forced to 32px |
106
+ | `ScProfileOptions` | the legacy static profile menu header |
107
+ | `ScSidebarProfile` | the pre-`StreamoidSidebar` sidebar footer |
108
+ | `ScTableList` | the member cell of a team-table row |
109
+ | `ScReferralTableList` | the referred-user cell |
110
+
111
+ If you are building a host screen, you almost certainly want one of those parents.
112
+
113
+ ---
114
+
115
+ ## 3. When to use it
116
+
117
+ ### Use it when
118
+
119
+ - You are composing a **new DS component** that needs the standard person identity
120
+ row and want the type ramp, the 12px gap and the ellipsis behaviour for free.
121
+ - You need an expanded/collapsed identity pair that matches the sidebar shells.
122
+
123
+ ### Don't use it — reach for this instead
124
+
125
+ | Situation | Use instead |
126
+ |---|---|
127
+ | The whole profile dropdown (identity + workspace + menu + theme) | `ScProfilePopup` |
128
+ | A **workspace** identity row (rounded-rect logo, name + role) | `ScWorkspace` — but it is **not exported**; use `ScProfilePopup`/`ScWorkspaceSwitchCard` |
129
+ | Mobile profile block with left/right avatar placement | `ScProfileV2Mobile` |
130
+ | Just the avatar, with an initials fallback | `ScDp` |
131
+ | Editable avatar with upload/delete | `ScProfileImageUpdate` |
132
+ | A team-table member row | `ScTableList` (it already renders a `ScProfile`) |
133
+ | The account settings form (first/last/email) | compose `ScProfileImageUpdate` + `ScTextField`; see `ScProfileSettingsComp` for why not that |
134
+
135
+ ### Don't confuse with
136
+
137
+ | You may actually want | Not this |
138
+ |---|---|
139
+ | `ScWorkspace` — same layout, **workspace** semantics: `workspaceName`/`userRole`, `radius-md` logo | `ScProfile` is the person: `name`/`subText`, circular avatar |
140
+ | `ScProfileOptions` — the legacy hardcoded menu panel (className-only API) | `ScProfile` is just the header row of it |
141
+ | `ScProfilePopup` — the current, fully-propped menu panel | `ScProfile` renders no menu |
142
+ | `ScProfileSettingsComp` — a static account-form scaffold | unrelated to this row |
143
+ | `ScProfileV2Mobile` — the mobile twin, `email` + `dpPosition` props | different prop names, mobile surface |
144
+
145
+ ---
146
+
147
+ ## 4. Why to use it
148
+
149
+ - **The type ramp is the spec.** `text-sm/medium` over `text-xs/regular` with
150
+ `text-and-icons-primary` over `-tertiary` is the identity pattern used everywhere;
151
+ restating it by hand is how sidebars end up with mismatched name sizes.
152
+ - **Both lines already ellipsise.** `overflow: hidden` + `text-overflow: ellipsis` +
153
+ `nowrap` on each line, so long emails degrade instead of wrapping the row.
154
+ - **The collapsed variant is a single prop** and matches the sidebar's 40 → 32px
155
+ avatar step exactly.
156
+ - **One place to change.** Five DS parents render it, so the identity row stays
157
+ consistent across the popup, the sidebar footer and both tables.
158
+
159
+ ---
160
+
161
+ ## Gotchas
162
+
163
+ **1. `profileImage` has a broken default.** `"profile-image0.png"` is a Figma export
164
+ artefact. With no `src` override you ship a broken-image icon — and there is **no
165
+ initials fallback** (that is `ScDp`, which this component does not use).
166
+
167
+ ```tsx
168
+ // WRONG — broken image glyph
169
+ <ScProfile name={user.name} subText={user.email} />
170
+
171
+ // RIGHT
172
+ <ScProfile name={user.name} subText={user.email} profileImage={user.avatarUrl ?? FALLBACK} />
173
+ ```
174
+
175
+ This is why `ScProfilePopup` spreads `avatar` conditionally: pass no `avatar` to the
176
+ popup and this default leaks through.
177
+
178
+ **2. `collapsed` is a string.** `collapsed={true}` is a type error, and
179
+ `collapsed={String(isCollapsed)}` widens to `string`. Write the ternary.
180
+
181
+ ```tsx
182
+ // WRONG
183
+ <ScProfile collapsed={isCollapsed} />
184
+
185
+ // RIGHT
186
+ <ScProfile collapsed={isCollapsed ? "true" : "false"} />
187
+ ```
188
+
189
+ **3. It is 200px wide, always (expanded).** `.scProfile { width: 12.5rem }` is a
190
+ plain class rule. Inside a wider flex row it will not stretch — every DS parent
191
+ overrides it: `flex: 1 !important; width: unset !important` in `ScProfilePopup`
192
+ (plus `min-width: 0 !important`), `ScProfileOptions`, `ScTableList` and
193
+ `ScReferralTableList`; `align-self: stretch !important; width: unset !important` in
194
+ `ScSidebarProfile`. Do the same, or pass
195
+ `style={{ flex: 1, width: "auto", minWidth: 0 }}`.
196
+
197
+ **4. Unconditional `className` concatenation.** The root class string is
198
+ `` `${styles.scProfile} ${className} ${variantsClassName}` ``, so with no
199
+ `className` the DOM gets `class="scProfile undefined collapsed-false"`. Don't assert
200
+ on the exact class string in tests.
201
+
202
+ **5. The `<img>` has no `alt` attribute at all.** Not `alt=""` — absent. Screen
203
+ readers may announce the filename. Wrap the row in a labelled element.
204
+
205
+ **6. It is a `<div>`, and props are spread.** `onClick` will fire, but you get no
206
+ `role`, no `tabIndex`, no keyboard activation and no focus ring. Wrap it in a real
207
+ `<button>` if it opens something.
208
+
209
+ **7. Trailing spaces in the text nodes.** Both lines render `{name} ` / `{subText} `
210
+ with a literal trailing space (Figma export). Exact-string assertions in tests need
211
+ a `trim()`.
212
+
213
+ ---
214
+
215
+ ## In the wild
216
+
217
+ _No host render site found — used by the agent runtime / composed internally._
218
+
219
+ It is composed inside `ScProfilePopup` (`src/SC-ProfilePopup/ScProfilePopup.tsx:235`),
220
+ `ScTableList`, `ScReferralTableList`, `ScSidebarProfile` and `ScProfileOptions`. The
221
+ nearest host surface is Catalogix's profile menu
222
+ (`app/components/AppSettingsPopup/index.jsx:75`), which reaches it **through**
223
+ `ScProfilePopup` — that is the intended entry point for hosts. Direct host use would
224
+ belong in a bespoke sidebar footer or member row that no app currently hand-rolls.
225
+
226
+ ---
227
+
228
+ ## Related
229
+
230
+ - `ScProfilePopup` — the current profile menu panel; renders this as its header.
231
+ - `ScWorkspace` — the workspace-flavoured twin (internal, not exported).
232
+ - `ScDp` — avatar only, with an image-error fallback this component lacks.
233
+ - `ScProfileV2Mobile` — the mobile identity block.
234
+ - `ScSidebarProfile` — legacy sidebar footer wrapper (superseded by `StreamoidSidebar`).