@d4gger/design-system 4.0.0 → 4.0.1

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 (147) hide show
  1. package/dist/brand-effects.css +5 -3
  2. package/dist/components/alert/Alert.cjs +17 -3
  3. package/dist/components/alert/Alert.cjs.map +2 -2
  4. package/dist/components/alert/Alert.d.cts +6 -0
  5. package/dist/components/alert/Alert.d.cts.map +1 -1
  6. package/dist/components/alert/Alert.d.mts +6 -0
  7. package/dist/components/alert/Alert.d.mts.map +1 -1
  8. package/dist/components/alert/Alert.d.ts +6 -0
  9. package/dist/components/alert/Alert.d.ts.map +1 -1
  10. package/dist/components/alert/Alert.js +17 -3
  11. package/dist/components/alert/Alert.js.map +2 -2
  12. package/dist/components/alert.css +62 -5
  13. package/dist/components/bottom-dock.css +8 -0
  14. package/dist/components/bottomDock/BottomDock.cjs +1 -1
  15. package/dist/components/bottomDock/BottomDock.cjs.map +2 -2
  16. package/dist/components/bottomDock/BottomDock.js +1 -1
  17. package/dist/components/bottomDock/BottomDock.js.map +2 -2
  18. package/dist/components/bottomDock/bottomDock.props.cjs +1 -1
  19. package/dist/components/bottomDock/bottomDock.props.cjs.map +2 -2
  20. package/dist/components/bottomDock/bottomDock.props.d.cts +2 -2
  21. package/dist/components/bottomDock/bottomDock.props.d.cts.map +1 -1
  22. package/dist/components/bottomDock/bottomDock.props.d.mts +2 -2
  23. package/dist/components/bottomDock/bottomDock.props.d.mts.map +1 -1
  24. package/dist/components/bottomDock/bottomDock.props.d.ts +2 -2
  25. package/dist/components/bottomDock/bottomDock.props.d.ts.map +1 -1
  26. package/dist/components/bottomDock/bottomDock.props.js +1 -1
  27. package/dist/components/bottomDock/bottomDock.props.js.map +2 -2
  28. package/dist/components/card.css +1 -1
  29. package/dist/components/collapsible/Collapsible.cjs +10 -0
  30. package/dist/components/collapsible/Collapsible.cjs.map +2 -2
  31. package/dist/components/collapsible/Collapsible.d.cts.map +1 -1
  32. package/dist/components/collapsible/Collapsible.d.mts.map +1 -1
  33. package/dist/components/collapsible/Collapsible.d.ts.map +1 -1
  34. package/dist/components/collapsible/Collapsible.js +10 -0
  35. package/dist/components/collapsible/Collapsible.js.map +2 -2
  36. package/dist/components/dialog.css +1 -1
  37. package/dist/components/environment-ribbon.css +73 -0
  38. package/dist/components/environmentRibbon/EnvironmentRibbon.cjs +69 -0
  39. package/dist/components/environmentRibbon/EnvironmentRibbon.cjs.map +7 -0
  40. package/dist/components/environmentRibbon/EnvironmentRibbon.d.cts +15 -0
  41. package/dist/components/environmentRibbon/EnvironmentRibbon.d.cts.map +1 -0
  42. package/dist/components/environmentRibbon/EnvironmentRibbon.d.mts +15 -0
  43. package/dist/components/environmentRibbon/EnvironmentRibbon.d.mts.map +1 -0
  44. package/dist/components/environmentRibbon/EnvironmentRibbon.d.ts +15 -0
  45. package/dist/components/environmentRibbon/EnvironmentRibbon.d.ts.map +1 -0
  46. package/dist/components/environmentRibbon/EnvironmentRibbon.js +39 -0
  47. package/dist/components/environmentRibbon/EnvironmentRibbon.js.map +7 -0
  48. package/dist/components/environmentRibbon/environmentRibbon.props.cjs +39 -0
  49. package/dist/components/environmentRibbon/environmentRibbon.props.cjs.map +7 -0
  50. package/dist/components/environmentRibbon/environmentRibbon.props.d.cts +18 -0
  51. package/dist/components/environmentRibbon/environmentRibbon.props.d.cts.map +1 -0
  52. package/dist/components/environmentRibbon/environmentRibbon.props.d.mts +18 -0
  53. package/dist/components/environmentRibbon/environmentRibbon.props.d.mts.map +1 -0
  54. package/dist/components/environmentRibbon/environmentRibbon.props.d.ts +18 -0
  55. package/dist/components/environmentRibbon/environmentRibbon.props.d.ts.map +1 -0
  56. package/dist/components/environmentRibbon/environmentRibbon.props.js +19 -0
  57. package/dist/components/environmentRibbon/environmentRibbon.props.js.map +7 -0
  58. package/dist/components/field.css +5 -0
  59. package/dist/components/icon/Icon.cjs +16 -0
  60. package/dist/components/icon/Icon.cjs.map +2 -2
  61. package/dist/components/icon/Icon.d.cts +25 -1
  62. package/dist/components/icon/Icon.d.cts.map +1 -1
  63. package/dist/components/icon/Icon.d.mts +25 -1
  64. package/dist/components/icon/Icon.d.mts.map +1 -1
  65. package/dist/components/icon/Icon.d.ts +25 -1
  66. package/dist/components/icon/Icon.d.ts.map +1 -1
  67. package/dist/components/icon/Icon.js +21 -0
  68. package/dist/components/icon/Icon.js.map +2 -2
  69. package/dist/components/icon/icons.cjs +12 -0
  70. package/dist/components/icon/icons.cjs.map +2 -2
  71. package/dist/components/icon/icons.d.cts +30 -0
  72. package/dist/components/icon/icons.d.cts.map +1 -1
  73. package/dist/components/icon/icons.d.mts +30 -0
  74. package/dist/components/icon/icons.d.mts.map +1 -1
  75. package/dist/components/icon/icons.d.ts +30 -0
  76. package/dist/components/icon/icons.d.ts.map +1 -1
  77. package/dist/components/icon/icons.js +12 -0
  78. package/dist/components/icon/icons.js.map +2 -2
  79. package/dist/components/index.cjs +1 -0
  80. package/dist/components/index.cjs.map +2 -2
  81. package/dist/components/index.d.cts +1 -0
  82. package/dist/components/index.d.cts.map +1 -1
  83. package/dist/components/index.d.mts +1 -0
  84. package/dist/components/index.d.mts.map +1 -1
  85. package/dist/components/index.d.ts +1 -0
  86. package/dist/components/index.d.ts.map +1 -1
  87. package/dist/components/index.js +1 -0
  88. package/dist/components/index.js.map +2 -2
  89. package/dist/components/notification-center.css +17 -9
  90. package/dist/components/notificationCenter/NotificationCenter.cjs +7 -2
  91. package/dist/components/notificationCenter/NotificationCenter.cjs.map +2 -2
  92. package/dist/components/notificationCenter/NotificationCenter.d.cts +2 -0
  93. package/dist/components/notificationCenter/NotificationCenter.d.cts.map +1 -1
  94. package/dist/components/notificationCenter/NotificationCenter.d.mts +2 -0
  95. package/dist/components/notificationCenter/NotificationCenter.d.mts.map +1 -1
  96. package/dist/components/notificationCenter/NotificationCenter.d.ts +2 -0
  97. package/dist/components/notificationCenter/NotificationCenter.d.ts.map +1 -1
  98. package/dist/components/notificationCenter/NotificationCenter.js +7 -2
  99. package/dist/components/notificationCenter/NotificationCenter.js.map +2 -2
  100. package/dist/components/page-header.css +21 -0
  101. package/dist/components/pageHeader/PageHeader.cjs +10 -2
  102. package/dist/components/pageHeader/PageHeader.cjs.map +2 -2
  103. package/dist/components/pageHeader/PageHeader.d.cts.map +1 -1
  104. package/dist/components/pageHeader/PageHeader.d.mts.map +1 -1
  105. package/dist/components/pageHeader/PageHeader.d.ts.map +1 -1
  106. package/dist/components/pageHeader/PageHeader.js +10 -2
  107. package/dist/components/pageHeader/PageHeader.js.map +2 -2
  108. package/dist/components/pageHeader/pageHeader.props.cjs +7 -1
  109. package/dist/components/pageHeader/pageHeader.props.cjs.map +2 -2
  110. package/dist/components/pageHeader/pageHeader.props.d.cts +5 -0
  111. package/dist/components/pageHeader/pageHeader.props.d.cts.map +1 -1
  112. package/dist/components/pageHeader/pageHeader.props.d.mts +5 -0
  113. package/dist/components/pageHeader/pageHeader.props.d.mts.map +1 -1
  114. package/dist/components/pageHeader/pageHeader.props.d.ts +5 -0
  115. package/dist/components/pageHeader/pageHeader.props.d.ts.map +1 -1
  116. package/dist/components/pageHeader/pageHeader.props.js +7 -1
  117. package/dist/components/pageHeader/pageHeader.props.js.map +2 -2
  118. package/dist/components/sidebar/Sidebar.cjs +6 -2
  119. package/dist/components/sidebar/Sidebar.cjs.map +2 -2
  120. package/dist/components/sidebar/Sidebar.d.cts +8 -0
  121. package/dist/components/sidebar/Sidebar.d.cts.map +1 -1
  122. package/dist/components/sidebar/Sidebar.d.mts +8 -0
  123. package/dist/components/sidebar/Sidebar.d.mts.map +1 -1
  124. package/dist/components/sidebar/Sidebar.d.ts +8 -0
  125. package/dist/components/sidebar/Sidebar.d.ts.map +1 -1
  126. package/dist/components/sidebar/Sidebar.js +6 -2
  127. package/dist/components/sidebar/Sidebar.js.map +2 -2
  128. package/dist/components/sidebar.css +58 -13
  129. package/dist/components.css +1 -0
  130. package/dist/docs/README.md +1 -0
  131. package/dist/docs/component-contract.md +5 -3
  132. package/dist/docs/component-index.json +9 -1
  133. package/dist/docs/components/alert.md +28 -8
  134. package/dist/docs/components/bottom-dock.md +4 -4
  135. package/dist/docs/components/card.md +1 -1
  136. package/dist/docs/components/collapsible.md +5 -0
  137. package/dist/docs/components/dialog.md +1 -1
  138. package/dist/docs/components/environment-ribbon.md +126 -0
  139. package/dist/docs/components/field.md +2 -0
  140. package/dist/docs/components/icon.md +1 -0
  141. package/dist/docs/components/notification-center.md +14 -9
  142. package/dist/docs/components/page-header.md +18 -6
  143. package/dist/docs/components/sidebar.md +17 -6
  144. package/dist/docs/consumer-guide.md +11 -4
  145. package/dist/styles.css +270 -30
  146. package/dist/tokens.css +2 -0
  147. package/package.json +1 -1
@@ -29,7 +29,7 @@ An inbox-style notification surface that groups header, list, and footer regions
29
29
  | `NotificationCenter.List` | `<div>` (or `Slot` host) | `dsx-notification-center__list` | Vertical list of items. Capped at `max-height: 400px` with `overflow-y: auto`. |
30
30
  | `NotificationCenter.Footer` | `<div>` (or `Slot` host) | `dsx-notification-center__footer` | Footer row (typically a "View all" link or button). |
31
31
  | `NotificationCenter.Item` | `<div>` (or `Slot` host) | `dsx-notification-center__item` (with `--unread` modifier when `unread` is true) | A single notification row. The CSS file ships helper classes `dsx-notification-center__item-title`, `dsx-notification-center__item-description`, and `dsx-notification-center__item-time` for the typical layout. |
32
- | `NotificationCenter.Trigger` | `IconButton` containing Icon + Badge | `dsx-notification-center__trigger` and `dsx-notification-center__badge` | Bell-style trigger (size `sm`, variant `ghost`) with an accessible unread-count name. The badge sits at the bell's upper trailing corner (capped at `'99+'`); the host reserves the count's width and asChild preserves child/ref composition. |
32
+ | `NotificationCenter.Trigger` | `IconButton` containing Icon + Badge | `dsx-notification-center__trigger` and `dsx-notification-center__badge` | Bell-style trigger (size `sm`, variant `ghost`) with an accessible unread-count name. The count hangs on the bell's upper trailing corner (capped at `'99+'`, or at `{max}+` when `max` is set) and the hover highlight covers the bell only; asChild preserves child/ref composition. |
33
33
 
34
34
  **Internal layout:**
35
35
 
@@ -37,7 +37,7 @@ An inbox-style notification surface that groups header, list, and footer regions
37
37
  - In the `popover` variant (the default), the root is sized `width: var(--dsx-sheet-width-sm), max-width: 100%`, has a `var(--dsx-rounded-lg)` radius, a 1px outline, an `var(--dsx-color-panel-translucent)` background, and a `var(--dsx-shadow-card-md)` shadow.
38
38
  - In the `sidebar` variant, the root is full-width / full-height with a flat `var(--dsx-color-surface)` background and no border or shadow.
39
39
  - `NotificationCenter.Item` rows have a `var(--dsx-space-md)` padding and a 1px bottom border. The last item drops the bottom border. The item background switches to `var(--dsx-color-surface-raised)` with a 1px primary left border when `unread` is true.
40
- - `NotificationCenter.Trigger` is an `inline-flex` button with intrinsic width and a 44px minimum width/height (`size-xl + space-xs`). The 16px badge is raised by 8px at the bell's trailing corner, with a 4px horizontal overlap and 8px host padding. Normal flow reserves the badge width; increasing counts grow toward the trailing edge rather than covering the bell. The badge uses rounded-full and label-small typography.
40
+ - `NotificationCenter.Trigger` is an ordinary `IconButton` (size `sm`, 32px, the same shape as every other header icon), so its hover highlight covers the bell only (G-20, 2026-10-05; it used to be a 59×44 pill that wrapped the count). The count is absolutely positioned on the bell's upper trailing corner: raised by `space-sm`, starting `space-xs` past the glyph's centre, so a constant 4px of it overlaps the bell and wider counts grow toward the trailing edge. The trigger reserves `space-md` after itself for the count, always, so the controls after it do not move when a count appears. A pseudo-element keeps the hit area at 44px (`size-xl + space-xs`) around the 32px highlight. The badge uses rounded-full and label-small typography.
41
41
 
42
42
  ## Props contract
43
43
 
@@ -64,7 +64,8 @@ These three slots accept only `asChild` plus the standard HTML attribute surface
64
64
 
65
65
  | Prop | Type | Default | Required | Description | Responsive |
66
66
  |---|---|---|---|---|---|
67
- | `unreadCount` | `number` | `undefined` | no | Unread count rendered as a `Badge` (capped at `'99+'`). The badge is only rendered when the count is greater than zero. | no |
67
+ | `unreadCount` | `number` | `undefined` | no | Unread count rendered as a `Badge` (capped at `max`, `'99+'` by default). The badge is only rendered when the count is greater than zero. | no |
68
+ | `max` | `number` | `99` | no | Largest count the badge draws; above it the badge reads `{max}+` (core's bell uses `9`). A value that is not a positive whole number falls back to `99`. The accessible name keeps the real count (“Notifications, 12 unread”), and `max` is not written to the DOM. Follows MUI `Badge` `max` and Ant Design `overflowCount`. | no |
68
69
  | `aria-label` | `string` | `'Notifications'` | no | Accessible name on the underlying `IconButton`. Override to localize or to disambiguate when more than one trigger is on the page. | no |
69
70
  | `asChild` | `boolean` | `false` | no | Polymorphic host. | no |
70
71
 
@@ -138,9 +139,10 @@ Every CSS value the component paints is a `var(--dsx-*)` token.
138
139
  | Item time type ramp | `var(--dsx-typography-label-small-*)` | Item time text |
139
140
  | Footer padding | `var(--dsx-space-sm)` | Footer gutter |
140
141
  | Footer border-top | `var(--dsx-border-width-sm) solid var(--dsx-color-outline-variant)` | Footer separator |
141
- | Trigger width / minimum dimensions | `auto` / `calc(var(--dsx-size-xl) + var(--dsx-space-xs))` | Count expands the 44px button |
142
- | Trigger gap / inline padding | `0` / `var(--dsx-space-sm)` | Count corner containment |
143
- | Badge placement | relative, raised by space-sm, negative space-xs inline margin | Upper trailing corner; reserves count width |
142
+ | Trigger size | the `IconButton` `sm` size (32px), no override | An ordinary header icon button; the highlight covers the bell only (G-20) |
143
+ | Trigger inline-end margin | `var(--dsx-space-md)` | Reserves the room the hanging count needs, always, so the controls after the bell do not move when a count appears |
144
+ | Trigger hit area | `::after`, `inset: calc((100% - (var(--dsx-size-xl) + var(--dsx-space-xs))) / 2)` | A 44px target around the 32px highlight (the inset shrinks to nothing on a larger size) |
145
+ | Badge placement | absolute, `top: calc(-1 * var(--dsx-space-sm))`, `inset-inline-start: calc(50% + var(--dsx-space-xs))` | Upper trailing corner, a constant 4px overlap with the bell glyph; wider counts grow toward the trailing edge |
144
146
  | Badge min-width | `var(--dsx-size-sm)` | Badge min width |
145
147
  | Badge height | `var(--dsx-size-sm)` | Badge height |
146
148
  | Badge radius | `var(--dsx-rounded-full)` | Badge roundness |
@@ -160,7 +162,7 @@ The component has no motion. The panel itself is static; transitions on open / c
160
162
 
161
163
  - The root renders as a `<div>` without an explicit `role`. The canonical pattern is to wrap the panel in a `Popover` or `Sheet`; the wrapping surface is responsible for the modal / non-modal role and focus management.
162
164
  - `NotificationCenter.List` is a plain `<div>`. If the consumer wants to expose the list as an `aria-live` region (e.g. for incoming notifications), they can add the `aria-live` and `aria-relevant` attributes manually.
163
- - `NotificationCenter.Trigger` renders an IconButton named “Notifications” at zero, or “Notifications, N unread” when positive. An explicit aria-label overrides this fallback. The visual badge is aria-hidden; it stays at the bell's upper trailing corner inside the trigger host.
165
+ - `NotificationCenter.Trigger` renders an IconButton named “Notifications” at zero, or “Notifications, N unread” when positive. An explicit aria-label overrides this fallback. The visual badge is aria-hidden; it hangs on the bell's upper trailing corner.
164
166
 
165
167
  **Keyboard:**
166
168
 
@@ -172,7 +174,7 @@ The component has no motion. The panel itself is static; transitions on open / c
172
174
  **Focus:**
173
175
 
174
176
  - The component does not render a focus ring on items or panels. Interactive content provides its own ring.
175
- - The trigger button gets the standard `IconButton` focus ring and a minimum 44px target containing both the bell and count.
177
+ - The trigger button gets the standard `IconButton` focus ring. Its visible box is 32px; a pseudo-element extends the hit area to 44px around the bell. The count hangs outside the box and is not part of the target (it is aria-hidden; the accessible name carries the number).
176
178
 
177
179
  **Reduced motion:**
178
180
 
@@ -204,6 +206,9 @@ The component has no motion. The panel itself is static; transitions on open / c
204
206
  - Renders an `Item` with `unread`. Asserts `data-unread="true"` and the `--unread` modifier class.
205
207
  - Renders a `Trigger` with `unreadCount={5}`. Asserts the badge text is `'5'`.
206
208
  - Renders a `Trigger` with `unreadCount={150}`. Asserts the badge text is `'99+'`.
209
+ - Renders a `Trigger` with `unreadCount={12}` and `max={9}`. Asserts the badge text is `'9+'` and the accessible name still reads “Notifications, 12 unread”. A count equal to `max` draws the number; an invalid `max` (0, negative, fractional, NaN) falls back to `'99+'`.
210
+
211
+ - `src/test/styles/shell-look-pass.test.ts` guards the trigger's CSS contract (an ordinary icon button, a corner-anchored count, the 44px hit-area pseudo-element, the reserved margin); `apps/playground/tests/overlay-feedback-review.spec.ts` measures the geometry and the hit area at 1280 / 390 / 320px. They supersede the earlier contract (a control of at least 44×44 with the count contained in it) (G-20, 2026-10-05).
207
212
 
208
213
  **Composition story:**
209
214
 
@@ -229,7 +234,7 @@ The component has no motion. The panel itself is static; transitions on open / c
229
234
  **Composes from:**
230
235
 
231
236
  - `IconButton` (`src/components/iconButton`): the trigger renders a small ghost `IconButton`. The trigger forwards all `IconButton` props and defaults `aria-label="Notifications"`.
232
- - `Badge` (`src/components/badge`): the trigger badge is a `Badge` with `variant="primary"`, `size="sm"`. The count is rendered as plain text and is capped at `'99+'` for counts greater than 99.
237
+ - `Badge` (`src/components/badge`): the trigger badge is a `Badge` with `variant="primary"`, `size="sm"`. The count is rendered as plain text and is capped at `'99+'` (or `{max}+` when `max` is set) for counts greater than the cap.
233
238
  - `@radix-ui/react-slot`: enables `asChild` on the root and on the named slots.
234
239
 
235
240
  **Used by:**
@@ -13,7 +13,7 @@ depends_on:
13
13
 
14
14
  ## Purpose
15
15
 
16
- A fixed-height header bar for the content area of a cabinet/shell layout: a title on the left, trailing actions on the right. Designed to be the first child inside `.dsx-sidebar__inset` (the content column `Sidebar` leaves for the app to fill), so every app screen shares one header height and padding scale instead of inventing its own.
16
+ A fixed-height header bar for the content area of a cabinet/shell layout: a title on the left, trailing actions on the right. Designed to be the first child inside `.dsx-sidebar__inset` (the content column `Sidebar` leaves for the app to fill), so every app screen shares one header height and padding scale instead of inventing its own. A `floating` variant draws the same bar as a glass panel with its own edge, for shells whose content column sits beside a floating sidebar (direction C of the `frontend` vision).
17
17
 
18
18
  ## Anatomy & slots
19
19
 
@@ -23,7 +23,7 @@ A fixed-height header bar for the content area of a cabinet/shell layout: a titl
23
23
 
24
24
  | Slot | Element | Renders | Notes |
25
25
  |---|---|---|---|
26
- | `PageHeader.Root` | `<div>` | `dsx-page-header` | Fixed-height flex row, `justify-content: space-between`. Holds `Title` and `Actions`. |
26
+ | `PageHeader.Root` | `<div>` | `dsx-page-header` + `data-variant` | Fixed-height flex row, `justify-content: space-between`. Holds `Title` and `Actions`. |
27
27
  | `PageHeader.Title` | `<h1>` | `dsx-page-header__title` | The page's h1. Single-line, truncates with ellipsis rather than wrapping. |
28
28
  | `PageHeader.Actions` | `<div>` | `dsx-page-header__actions` | Trailing flex row for buttons/icon buttons. Optional — a header with only a title is valid (see empty-state test). |
29
29
 
@@ -31,6 +31,7 @@ A fixed-height header bar for the content area of a cabinet/shell layout: a titl
31
31
 
32
32
  | Prop | Type | Default | Required | Description | Responsive |
33
33
  |---|---|---|---|---|---|
34
+ | `variant` | `'default' \| 'floating'` | `'default'` | no | Surface treatment; writes `data-variant`. `default`: the flat opaque bar with a bottom rule. `floating`: a glass panel with its own edge, radius and shadow (the `Card variant="glass"` recipe). The height and the slots are the same in both. | no |
34
35
  | `asChild` | `boolean` | `false` | no | Renders `Root` through `Slot`; consumer supplies the host element. | no |
35
36
  | `className` | `string` | `undefined` | no | Extra classes appended to `dsx-page-header`. | no |
36
37
  | `children` | `React.ReactNode` | `undefined` | no | Typically `PageHeader.Title` followed by an optional `PageHeader.Actions`. | no |
@@ -39,14 +40,14 @@ A fixed-height header bar for the content area of a cabinet/shell layout: a titl
39
40
 
40
41
  Rules that apply to this row:
41
42
 
42
- - `PageHeader` is a behavioral/layout composite, not a styled variant surface. It does not run a `variant` or `size` prop def — one shape, one height.
43
+ - `PageHeader` has one height at every width and no `size` axis. Its only axis is `variant` (`default` / `floating`), which changes the surface, never the height. An unknown value falls back to `default`.
43
44
  - `PageHeader.Title` renders `h1` by default. A page should have exactly one; nested `Theme`/route-level headings should not duplicate it.
44
45
 
45
46
  ## CSS class contract
46
47
 
47
48
  **Root class:** `dsx-page-header`
48
49
 
49
- **Modifier classes:** none. No `data-variant`/`data-size` — the header has one fixed shape.
50
+ **Modifier attributes:** `data-variant` (`default`, `floating`), written by the component; `.dsx-page-header:where([data-variant='floating'])` in `page-header.css` carries the glass surface. No `data-size` — the header has one fixed height.
50
51
 
51
52
  **Slot classes:**
52
53
 
@@ -73,6 +74,12 @@ Rules that apply to this row:
73
74
  | Gap | `var(--dsx-space-md)` | Gap between title and actions when both are near the edge. |
74
75
  | Border (bottom) | `var(--dsx-border-width-sm)` + `var(--dsx-color-outline-variant)` | Separates the header from scrolled content below it. |
75
76
  | Background | `var(--dsx-color-surface)` | Matches the surrounding shell surface. |
77
+ | Floating edge | `var(--dsx-border-width-sm)` + `var(--dsx-effect-panel-glass-border)` on all four sides | `variant="floating"`; replaces the bottom rule. |
78
+ | Floating radius | `var(--dsx-rounded-lg)` | `variant="floating"`; the same as `Card`'s default radius. |
79
+ | Floating surface | `var(--dsx-color-panel-translucent)` | `variant="floating"`; the glass fill. |
80
+ | Floating rim | `var(--dsx-effect-panel-glass-rim-highlight)`, `var(--dsx-effect-panel-glass-rim)` | `variant="floating"`; the same two inset layers as `Card variant="glass"`. |
81
+ | Floating shadow | `0 var(--dsx-shadow-offset-lg) var(--dsx-shadow-blur-md) calc(-1 * var(--dsx-shadow-offset-lg)) var(--dsx-effect-shadow-card-strong)` | `variant="floating"`; the shadow falls below the bar only (offset equals the negative spread, so it starts at the bar's bottom edge). The bar sits flush at the edge of a scroll container (`Sidebar.Inset`, `overflow: auto`) that clips what is painted past its left, right and top edges, so the full-ring `--dsx-shadow-panel-shadow` ended in a vertical cut at the bar's side in the light theme (G-21). This is the one place the floating bar differs from `Card variant="glass"`. Guarded by `src/test/styles/page-header-shadow.test.ts`. |
82
+ | Floating blur | `var(--dsx-effect-panel-glass-backdrop-filter)` | `variant="floating"`; declared as `-webkit-backdrop-filter` first, `backdrop-filter` last (see `card.md`). |
76
83
  | Title font | `var(--dsx-typography-headline-medium-*)` family | 24px/600, the DS's headline-medium scale — sized for a 72px bar. |
77
84
  | Title color | `var(--dsx-color-on-surface)` | Primary text. |
78
85
  | Actions gap | `var(--dsx-space-sm)` | Gap between action buttons. |
@@ -80,6 +87,7 @@ Rules that apply to this row:
80
87
  Rules:
81
88
 
82
89
  - No raw px/color values in `page-header.css`. The 72px height is a `calc()` of two spacing tokens, not a hardcoded value.
90
+ - The floating blur only shows when content passes under the bar (a sticky header over a scrolling page). The DS does not make the bar sticky or give it a margin: the page decides where it sits.
83
91
 
84
92
  ## Motion contract
85
93
 
@@ -131,6 +139,10 @@ The live example uses a compact named icon action so the title remains readable
131
139
 
132
140
  - Renders `PageHeader` with both `Title` and `Actions` (one or two buttons). Asserts both slots render with their classes.
133
141
 
142
+ **Variant story:**
143
+
144
+ - Renders `PageHeader` with `variant="default"` and `variant="floating"`. Asserts the matching `data-variant` attribute; the floating bar keeps the title and actions slots and the same height.
145
+
134
146
  **Empty-state story:**
135
147
 
136
148
  - Renders `PageHeader` with only `Title`, no `Actions` — the header still renders correctly with no trailing content.
@@ -145,7 +157,7 @@ The live example uses a compact named icon action so the title remains readable
145
157
  |---|---|---|
146
158
  | (not exposed) | n/a | n/a |
147
159
 
148
- `PageHeader` has no variant/size axis to expose; the playground demonstrates it via a static composition fixture (title + actions) rather than a controls panel.
160
+ `PageHeader` has no size axis, and its `variant` is shown as two fixtures (default and floating) in one composition rather than a controls panel.
149
161
 
150
162
  ## Wiring notes
151
163
 
@@ -159,7 +171,7 @@ The live example uses a compact named icon action so the title remains readable
159
171
 
160
172
  **State boundaries:**
161
173
 
162
- - Owned by `PageHeader`: the root class, fixed height, padding, and the two slot classes.
174
+ - Owned by `PageHeader`: the root class, `data-variant`, the fixed height, padding, the surface of each variant, and the two slot classes.
163
175
  - Owned by the consumer: the title text, which actions render, and their handlers.
164
176
 
165
177
  **Boundary rules:**
@@ -46,14 +46,14 @@ A panel and cabinet shell navigation surface. The DS `Sidebar` exposes a provide
46
46
  | `Sidebar.MenuBadge` | `<span>` | `dsx-sidebar__menu-badge` plus the text Badge classes or the `--ring` / `--accent` modifier + `data-slot="sidebar-menu-badge"` + `data-state` | A count, proportional usage ring, or quiet accent value. Remains in the DOM but is visually hidden when the panel collapses. |
47
47
  | `Sidebar.MenuAction` | `<button>` (or `Slot` child when `asChild`) | `dsx-sidebar__menu-action dsx-button` + `data-slot="sidebar-menu-action"` + `data-state` | An action button revealed on hover. |
48
48
  | `Sidebar.MenuButton` | `<button>` (or `Slot` child when `asChild`) | `dsx-sidebar__menu-button dsx-button` + `dsx-sidebar__menu-button-text` (when children are a string or number) + `data-slot="sidebar-menu-button"` + `data-active` + `data-state` | A menu button. |
49
- | `Sidebar.MenuSkeleton` | `<div>` | `dsx-sidebar__menu-skeleton` + `dsx-skeleton dsx-skeleton--circle` (icon) + `dsx-skeleton dsx-skeleton--text-line` (label) + `data-slot="sidebar-menu-skeleton"` + `data-show-icon` + `data-state` | A loading placeholder for a menu row. |
49
+ | `Sidebar.MenuSkeleton` | `<div>` | `dsx-sidebar__menu-skeleton` + `dsx-skeleton dsx-skeleton--circle` (icon) + `dsx-skeleton dsx-skeleton--text-line` (label) + `data-slot="sidebar-menu-skeleton"` + `data-show-icon` + `data-state` | A loading placeholder for a menu row. Inside a `Sidebar.MenuItem` (a flex row) it takes the item's width (`.dsx-sidebar__menu-item > .dsx-sidebar__menu-skeleton { flex: 1 }`); on its own it is as wide as its parent. |
50
50
  | `Sidebar.MenuSub` | `<ul>` | `dsx-sidebar__menu-sub` + `data-slot="sidebar-menu-sub"` + `data-state` | A nested menu list. |
51
51
  | `Sidebar.MenuSubItem` | `<li>` | `dsx-sidebar__menu-sub-item` + `data-slot="sidebar-menu-sub-item"` + `data-state` | A nested menu row. |
52
52
  | `Sidebar.MenuSubButton` | `<button>` (or `Slot` child when `asChild`) | `dsx-sidebar__menu-sub-button dsx-button` + `dsx-sidebar__menu-button-text` (when children are a string or number) + `data-slot="sidebar-menu-sub-button"` + `data-active` + `data-state` | A nested menu button. |
53
53
  | `Sidebar.MenuSubTrigger` | `<button>` (or `Slot` child when `asChild`) | `dsx-sidebar__menu-sub-trigger dsx-button` + `dsx-sidebar__menu-sub-trigger-chevron` (`chevron-right`, rotates 90° on open) + `data-slot="sidebar-menu-sub-trigger"` + `data-state` (`open` \| `closed`) + `aria-expanded` | The parent button that toggles a `Sidebar.MenuSub`. Composes the public `Collapsible` primitive. Decided in Direction #4 Q5; `mode="both"` is rejected. |
54
54
  | `Sidebar.Separator` | `<div role="separator" aria-orientation="horizontal">` | `dsx-sidebar__separator dsx-separator dsx-separator--decorative` + `data-slot="sidebar-separator"` + `data-state` | A horizontal divider. |
55
55
  | `Sidebar.Trigger` | `<button aria-label="Expand sidebar" \| "Collapse sidebar" \| "Pin sidebar" \| "Unpin sidebar">` | `dsx-sidebar__trigger dsx-button` + `dsx-button__icon` (panel-state glyph) + `dsx-sidebar__trigger-label` (text) + `data-slot="sidebar-trigger"` + `data-state` | A toggle button used inside the panel or the inset. Hover-preview mode uses dashed/solid panel semantics instead of directional chevrons. |
56
- | `Sidebar.mobile-trigger` (internal) | `<button aria-label="Open sidebar">` | `dsx-sidebar__mobile-trigger` + `data-slot="sidebar-mobile-trigger"` | The mobile sheet trigger, mounted by `Sidebar.Provider` when `mobile="sheet"` and the viewport is below `mobileBreakpoint`. |
56
+ | `Sidebar.mobile-trigger` (internal) | `<button aria-label="Open sidebar">` | `dsx-sidebar__mobile-trigger` + `data-slot="sidebar-mobile-trigger"` | The mobile sheet trigger, mounted by `Sidebar.Provider` when `mobile="sheet"` and the viewport is below `mobileBreakpoint`, unless `mobileTrigger` is `false`. |
57
57
  | `Sidebar.SkipLink` | `<a>` | `dsx-sidebar__skip-link` | Focus-revealed skip link targeting `targetId` (`main` by default). |
58
58
 
59
59
  The roster's `Parent / Slots` column lists every slot above plus `Sidebar.Inset` and `Sidebar.Trigger`. The source exports the full set through `Object.assign` on `Sidebar` (alias of `Sidebar.Root`), and also re-exports the named components individually. The spec records the runtime shape; the roster's slot list is the contract for canonical anatomy.
@@ -71,6 +71,7 @@ The roster's `Parent / Slots` column lists every slot above plus `Sidebar.Inset`
71
71
  | `hoverExpand` | `boolean` | `false` | no | In icon mode, temporarily expands the collapsed rail on pointer hover or keyboard focus. The preview overlays the inset and never changes the persisted preference. `Escape` closes a keyboard-opened preview. | no |
72
72
  | `previewOpen` | `boolean` | `false` | no | Holds the temporary icon-mode preview open for a consumer-owned flyout or other adjacent interaction. It does not change the persisted preference. | no |
73
73
  | `mobile` | `'sheet' \| 'drawer' \| 'none'` | `'sheet'` | no | Mobile fallback mode. `sheet` mounts a `Sheet` trigger; `none` skips the mobile fallback. | no |
74
+ | `mobileTrigger` | `boolean` | `true` | no | Whether the provider mounts its floating "Open sidebar" button in mobile sheet mode. Set `false` when the app opens the drawer from its own control, a header button or a dock item (`BottomDock`'s "More"), with `useSidebar().setMobileSheetOpen(true)`. The drawer, its own close button and its focus handling are unchanged; with `mobile="none"` the prop has no effect. Not written to the DOM. | no |
74
75
  | `mobileBreakpoint` | `number` | `768` | no | Viewport width below which the provider treats the device as mobile. The provider also matches `(pointer: coarse)`. | no |
75
76
  | `defaultSubmenuMode` | `'click' \| 'hover'` | `'click'` | no | Default toggle mode for every `Sidebar.MenuSubTrigger` under this provider. Individual triggers override per-section. | no |
76
77
  | `submenuOpenOnActive` | `boolean` | `true` | no | Default for `openOnActive` on every `Sidebar.MenuSubTrigger` under this provider. | no |
@@ -107,7 +108,7 @@ The roster's `Parent / Slots` column lists every slot above plus `Sidebar.Inset`
107
108
 
108
109
  ### `Sidebar.MenuSubTrigger`
109
110
 
110
- The parent button that toggles a `Sidebar.MenuSub`. Composes the public `Collapsible` primitive: the open state lives on a consumer-owned `Collapsible` root (`asChild` over the `MenuItem`), this trigger owns the click toggle and mirrors `open` / `onOpenChange` for hover timers, Arrow keys, and auto-open. `CollapsibleTrigger` is deliberately NOT in the composition (its span + chevron pair breaks Radix Slot's single-child rule). `CollapsibleContent` takes `forceMount` so the closed sub stays in the DOM and `openOnActive` can see an active descendant on mount. Direction #4 Q5 verdict: `click` is the default mode, `hover` is opt-in per trigger, `both` is rejected (hover/click race conditions). Hover mode is suppressed on coarse pointers and degrades to tap-to-toggle.
111
+ The parent button that toggles a `Sidebar.MenuSub`. Composes the public `Collapsible` primitive: the open state lives on a consumer-owned `Collapsible` root (`asChild` over the `MenuItem`), this trigger owns the click toggle and mirrors `open` / `onOpenChange` for hover timers, Arrow keys, and auto-open. `CollapsibleTrigger` is deliberately NOT in the composition (its span + chevron pair breaks Radix Slot's single-child rule). `CollapsibleContent` takes `forceMount` so the closed sub stays in the DOM and `openOnActive` can see an active descendant on mount; a sub that mounts closed is hidden at rest by the Collapsible's motion styles (`collapsible.md` § Force-mounted content, G-14), and a collapsed one is out of the tab order. The trigger is a row like any `MenuButton` (same padding, icon column, fill and type: G-13). Direction #4 Q5 verdict: `click` is the default mode, `hover` is opt-in per trigger, `both` is rejected (hover/click race conditions). Hover mode is suppressed on coarse pointers and degrades to tap-to-toggle.
111
112
 
112
113
  | Prop | Type | Default | Required | Description | Responsive |
113
114
  |---|---|---|---|---|---|
@@ -268,6 +269,8 @@ Rules:
268
269
 
269
270
  - The CSS file collapses the panel through the `data-state` attribute. The mobile sheet fallback is mounted by `Sidebar.Provider` based on `window.innerWidth` and `matchMedia('(pointer: coarse)')`, gated by `mobileBreakpoint` and the `mobile` prop.
270
271
  - The component does not write `@media` rules; the mobile behavior is runtime-driven, not CSS-driven.
272
+ - `dsx-sidebar__menu-sub-trigger` shares the base rule of `dsx-sidebar__menu-button` (display, `--dsx-space-sm` padding, transparent fill, no border, label type, `--dsx-shadow-focus-ring` on `:focus-visible`), so a parent row and a plain row have one geometry: the icon in the same column, no browser button fill when the parent is neither open nor active. Open and active states are the parent's own rules after it.
273
+ - The mobile drawer (`dsx-sidebar__mobile-sheet`) is flush with the viewport on three sides, so it keeps the structural border on its free inline-end edge only (`border-block-width: 0`, `border-inline-start-width: 0`), and it does not scroll itself (`overflow: hidden`): the nav fills it (`height: 100%`) and its content area owns the scrolling. The base dialog surface that Drawer shares draws the border all round, which is right for a floating panel and wrong for a full-height sheet.
271
274
 
272
275
  **Reduced motion:**
273
276
 
@@ -287,7 +290,9 @@ Every CSS value the component paints is a `var(--dsx-*)` token.
287
290
  | Panel width (icon collapsed) | `var(--dsx-sidebar-width-collapsed)` | Persistent slim icon rail. |
288
291
  | Panel preview layout | `calc(var(--dsx-sidebar-width-collapsed) - var(--dsx-sidebar-width))` | Negative inline-end margin lets temporary expansion overlay rather than reflow the inset. |
289
292
  | Panel background | `var(--dsx-color-surface)` | Panel surface. |
290
- | Panel ambient effect | `var(--dsx-color-accent-9)` mixed with transparency | Optional subscription-aware accent wash without a literal starfield. |
293
+ | Panel ambient effect | `var(--dsx-color-accent-9)` mixed with transparency at `var(--dsx-effect-ambient-strength)` (10% in dark, 16% in light), from the top-left corner, plus a second source at the foot: an ellipse anchored to the bottom edge at 0.9× the same strength | Optional subscription-aware accent wash without a literal starfield. The strength is theme-aware (G-16): the same wash read about half as strong on the pale light surface. The foot glow (G-17, 2026-10-05) lights the lower half the corner radial never reached (about 35% of the panel) and leaves the nav a calm middle. |
294
+ | Trigger | transparent fill, `inset 0 0 0 var(--dsx-border-width-sm) var(--dsx-color-accent-7)` ring, `var(--dsx-color-accent-11)` glyph; hover fill `var(--dsx-color-accent-3)` and ring `var(--dsx-color-accent-8)` | A quiet outline (G-18, 2026-10-05). The raised disc it replaced (`surface-raised` fill, drop shadow) vanished on dark, where shadows do not read, and on the tinted panel. Scale jobs: border step 7, text step 11, one step up on hover. The focus ring still replaces the ring; the pin / unpin glyphs of hover-expand mode live in the same button. |
295
+ | Active row wash (light) | `var(--dsx-color-accent-4)` on `MenuButton`, `MenuSubButton` and `MenuSubTrigger` when `data-active='true'`, under `:where([data-dsx-theme='light'])`; dark keeps `accent-3` at 50% | G-19 (2026-10-05): accent-3 at 50% over a tinted light panel is nearly the panel's colour, so in light the row was marked only by its underline and text. Step 4 is the scale's soft-component step. |
291
296
  | Panel border | `none` (CSS keyword) | The slim shell uses surface contrast and elevation instead of a boxed edge. |
292
297
  | Panel shadow | `var(--dsx-effect-shadow-1)` | Panel elevation. |
293
298
  | Floating: provider padding and gap | `var(--dsx-space-3)` | The space around the panel and between the panel and the inset. Never a sidebar margin: the preview and pin-docking motion animate `margin-inline-end` and `width`. |
@@ -368,7 +373,7 @@ Rules:
368
373
  - Offcanvas collapsed content is removed from interaction and the accessibility
369
374
  tree. The external recovery rail owns `aria-controls` and `aria-expanded`.
370
375
  - `Sidebar.GroupLabel` is a non-semantic `<div>`; consumers can set `role="heading"` plus `aria-level` when the label needs to be a heading.
371
- - The mobile sheet trigger (when mounted by `Sidebar.Provider`) is a button with `aria-label="Open sidebar"`.
376
+ - The mobile sheet trigger (when mounted by `Sidebar.Provider`) is a button with `aria-label="Open sidebar"`. With `mobileTrigger={false}` the app's own control carries that role and must be a real button with its own accessible name. The drawer's own labels ("Close navigation", "Navigation") are fixed English strings today.
372
377
  - `useSidebar` returns a no-op fallback when the consumer renders a sidebar slot outside `Sidebar.Provider`, so the component never throws.
373
378
 
374
379
  **Keyboard:**
@@ -421,13 +426,19 @@ Submenu parent triggers use `--dsx-rounded-sm`, matching navigation rows rather
421
426
  - Renders a `MenuButton` with `isActive` and asserts `data-active="true"` plus the `dsx-sidebar-menu-button-active` class. Toggles the panel via the `Rail` click and asserts the `data-state` flips on the provider, the panel, the header, the footer, and the content. Renders a `MenuBadge` with text `12` and asserts the badge stays in the DOM when the panel collapses while CSS visually hides it.
422
427
  - Renders `MenuBadge variant="accent"` as quiet numeric metadata without the filled Badge surface; `variant="ring"` remains reserved for a genuine `value / max` ratio.
423
428
 
429
+ **Mobile story:**
430
+
431
+ - At a phone width in `mobile="sheet"` mode, asserts the floating "Open sidebar" button is mounted by default, is absent with `mobileTrigger={false}` (checked next to a default provider, because the drawer's chunk is lazy), and that an app control calling `useSidebar().setMobileSheetOpen(true)` still opens the drawer. The registry has no phone-width fixture for this: the drawer is a portal bound to the window, so `Sidebar.test.tsx` and the `frontend` user-shell render carry it. `src/test/styles/sidebar-mobile-sheet.test.ts` guards the sheet's three CSS rules (free-edge border only, no own scroll, nav sized to the sheet); jsdom has no layout, so the scrollbar and outline themselves are proved in the browser (`docs/feature/design-system/sidebar-sheet-chrome/verification.md`).
432
+
424
433
  **Composition story:**
425
434
 
426
435
  - Renders a `Sidebar.Content` with two `Sidebar.Group` blocks, each containing a `GroupLabel`, a `GroupContent`, and a `Menu` with `MenuItem` and `MenuButton` rows. Adds a `Sidebar.Separator` between the groups and a `Sidebar.MenuSub` with `Sidebar.MenuSubItem` and `Sidebar.MenuSubButton` rows in one of the menus. Asserts every slot renders the right `dsx-sidebar__*` class.
436
+ - `src/test/styles/sidebar-sub-trigger-row.test.ts` guards the shared row base of `MenuButton` and `MenuSubTrigger` (padding, fill, border, focus ring): the parent row sat 8px right of the others and showed a grey button fill when idle (G-13, 2026-10-05). `Collapsible.test.tsx` guards the closed force-mounted panel (G-14).
437
+ - `src/test/styles/shell-look-pass.test.ts` guards the ambient wash's second source (G-17), the outline trigger and the order of its focus ring (G-18), and the light active-row wash with its (0,2,0) selector and source order (G-19); `apps/playground/tests/user-shell-frame-browser.spec.ts` measures all three on the user-shell frame for Rift, Warp and Ray in both themes.
427
438
 
428
439
  **Token story:**
429
440
 
430
- - Sidebar does not own a `data-accent-color` hook, so the token story is omitted. The active menu button background tracks `var(--dsx-color-accent-surface)` and the active text tracks `var(--dsx-color-accent-indicator)`, which are theme-aware.
441
+ - Sidebar does not own a `data-accent-color` hook, so the token story is omitted. The active row's wash is `var(--dsx-color-accent-3)` at 50% in dark and `var(--dsx-color-accent-4)` in light (G-19), and its text tracks `var(--dsx-color-accent-indicator)`, which is theme-aware.
431
442
 
432
443
  **A11y story:**
433
444
 
@@ -33,6 +33,13 @@ The optional `brand-effects.css` provides `dsx-brand-ambient`,
33
33
  `dsx-brand-starfield`, and `dsx-brand-shimmer`. Apply them to a page wrapper;
34
34
  core styles do not enable product atmosphere automatically.
35
35
 
36
+ The accent haze of `dsx-brand-ambient` (and of `Sidebar effect="ambient"`) follows
37
+ the theme-aware token `--dsx-effect-ambient-strength` (10% in dark, 16% in light;
38
+ the three washes of `dsx-brand-ambient` are 2.2×, 1.2× and 0.8× of it). Raise or
39
+ lower the haze for a theme by overriding the token on that theme's boundary, not by
40
+ copying the gradients. The sidebar's wash has two sources, the top-left corner and
41
+ the foot (the foot at 0.9× the same token), so one override moves both.
42
+
36
43
  Starfield density can be selected with `dsx-brand-starfield--sparse` or
37
44
  `dsx-brand-starfield--dense`. Fine-tune an individual wrapper with
38
45
  `--dsx-brand-starfield-opacity`, `--dsx-brand-starfield-dot-size`, and
@@ -847,12 +854,12 @@ const connectivity = dsxIconCatalog.filter(
847
854
  |---|---|
848
855
  | Theme | `sun`, `moon`, `monitor` |
849
856
  | Navigation | `arrow-left`, `arrow-right`, `chevron-down`, `chevron-up`, `chevron-left`, `chevron-right`, `menu`, `x`, `plus`, `minus`, `dots-horizontal`, `dots-vertical`, `external-link`, `home`, `search`, `settings`, `user` |
850
- | Feedback | `check`, `check-circle`, `info`, `help-circle`, `alert-triangle`, `bell`, `loader`, `sparkles`, `star` |
857
+ | Feedback | `check`, `check-circle`, `info`, `help-circle`, `alert-triangle`, `circle-alert`, `bell`, `loader`, `sparkles`, `star` |
851
858
  | Security | `shield`, `shield-check`, `lock`, `lock-keyhole`, `unlock`, `key`, `fingerprint`, `eye`, `eye-off` |
852
- | Connectivity | `wifi`, `signal`, `globe`, `server`, `hard-drive`, `activity`, `zap` |
853
- | Communication | `mail`, `send` |
859
+ | Connectivity | `wifi`, `signal`, `globe`, `server`, `hard-drive`, `smartphone`, `activity`, `zap` |
860
+ | Communication | `mail`, `send`, `message-square` |
854
861
  | Commerce | `banknote`, `circle-dollar-sign`, `gem`, `quote`, `receipt-text`, `russian-ruble` |
855
- | Forms & Actions | `edit`, `trash`, `copy`, `eraser`, `calendar`, `clock`, `code`, `file`, `image`, `link`, `list`, `list-ordered`, `upload`, `bold`, `italic`, `strikethrough`, `quote`, `heading-1`, `heading-2`, `heading-3`, `undo`, `redo` |
862
+ | Forms & Actions | `edit`, `trash`, `copy`, `eraser`, `calendar`, `clock`, `code`, `file`, `image`, `link`, `list`, `list-ordered`, `upload`, `paperclip`, `bold`, `italic`, `strikethrough`, `quote`, `heading-1`, `heading-2`, `heading-3`, `undo`, `redo`, `refresh-cw` |
856
863
  | Brand & Social | `apple`, `discord`, `facebook`, `github`, `gitlab`, `google`, `instagram`, `netflix`, `npm`, `paypal`, `reddit`, `spotify`, `stripe`, `supabase`, `telegram`, `twitch`, `twitter`, `vercel`, `youtube` |
857
864
  | App Specific | `home`, `rocket` |
858
865