@helloimjolopez-pathway/pathway-tokens 11.0.0 → 11.1.0

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.
@@ -43,8 +43,19 @@ export const SCROLL = {
43
43
  // an overlay scrollbar is a redundant affordance (the content scrolls with or
44
44
  // without it, and the OS bar remains). So contrast is bought back with SIZE
45
45
  // and PRESENCE rather than with darkness: see thumbWidth and the grab strip.
46
- thumbRest: "var(--semantic-color-scrim-faint)", // black 16% — faint overlay (rest)
47
- thumbHover: "var(--semantic-color-scrim-light)", // black 24% — hover/drag
46
+ // Scrim/Faint and Scrim/Light resolve to Cool Neutral 800, so the thumb was
47
+ // drawing a COOL grey over warm surfaces and reading as a cold bar against
48
+ // them. Reported 2026-10-02. The comment below has always said "light warm
49
+ // overlay" — the value simply did not match it.
50
+ //
51
+ // Scrim is also the wrong family: it is the modal backdrop, where a cool
52
+ // near-black is right. The thumb is an overlay on a surface, and under the
53
+ // alpha rule surfaces and fills are WARM. So the thumb now resolves through
54
+ // its own themed custom properties, set in the injected sheet below off the
55
+ // warm neutral alpha primitives. No new design token: a component-local
56
+ // property, the same mechanism the Widget uses for its column spans.
57
+ thumbRest: "var(--pw-scrollbar-thumb-rest)", // warm neutral 16%
58
+ thumbHover: "var(--pw-scrollbar-thumb-hover)", // warm neutral 24%
48
59
  thumbBlur: "blur(8px) saturate(180%)",
49
60
  // Hairline glass edge: semantic white at 35% via color-mix.
50
61
  thumbEdge: "inset 0 0 0 0.5px color-mix(in srgb, var(--semantic-color-fill-static-neutral-faint) 35%, transparent)",
@@ -72,6 +83,16 @@ if (typeof document !== "undefined" && !document.getElementById("pds-scrollable-
72
83
  const s = document.createElement("style");
73
84
  s.id = "pds-scrollable-base";
74
85
  s.textContent =
86
+ // Warm neutral, and it has to INVERT: 500 is the dark warm grey for a light
87
+ // surface, 100 the light warm grey for a dark one. An inline style cannot
88
+ // branch on [data-theme], which is why these live here rather than in the
89
+ // SCROLL map above.
90
+ ":root,[data-theme=\"light\"]{" +
91
+ "--pw-scrollbar-thumb-rest:var(--primitive-color-warm-neutral-500-16);" +
92
+ "--pw-scrollbar-thumb-hover:var(--primitive-color-warm-neutral-500-24)}" +
93
+ "[data-theme=\"midnight\"],[data-theme=\"dark\"]{" +
94
+ "--pw-scrollbar-thumb-rest:var(--primitive-color-warm-neutral-100-16);" +
95
+ "--pw-scrollbar-thumb-hover:var(--primitive-color-warm-neutral-100-24)}" +
75
96
  ".pds-scrollable__view{scrollbar-width:none;-ms-overflow-style:none}" +
76
97
  ".pds-scrollable__view::-webkit-scrollbar{width:0;height:0;display:none}" +
77
98
  "@media (hover: none){.pds-scrollable__grab{pointer-events:none!important}}";
@@ -139,6 +139,10 @@ export const L = {
139
139
  iconWrap: 24, // no token in Figma — leading icon wrapper
140
140
  iconInner: 16, // Material Symbols Rounded frame size, per design-system-spec §7.2
141
141
  rowPadH: u("padding-tight"),
142
+ // Collapsed rail: container.rowStart's padding-right in Figma. It is what
143
+ // keeps the centred icon a hair left of the square's true centre, the same as
144
+ // the design.
145
+ railIconInset: u("padding-xxtight"),
142
146
  textPad: u("padding-xtight"),
143
147
  childIndent: 24, // no token in Figma — level-1 left indent
144
148
  stripeW: 4, // no token in Figma — indicator stripe width
@@ -234,6 +238,13 @@ export function SideNavItem({
234
238
  width: isSidebarCollapsed ? L.itemH : "100%",
235
239
  marginLeft: isSidebarCollapsed ? "auto" : undefined,
236
240
  marginRight: isSidebarCollapsed ? "auto" : undefined,
241
+ // Figma's container.rowStart is 40 wide inside the 44 square with
242
+ // padding-right 6 and primary=CENTER, so the icon centres in the 34
243
+ // that is left after the 4px indicator column. See the icon wrap below.
244
+ paddingRight: isSidebarCollapsed ? L.railIconInset : undefined,
245
+ // border-box or the 6px padding is ADDED to the 44, which made the rail
246
+ // item 50 wide and no longer a square.
247
+ boxSizing: "border-box",
237
248
  borderRadius: T.radius, backgroundColor: fillBg,
238
249
  cursor: isDisabled ? "not-allowed" : "pointer",
239
250
  overflow: "hidden", transition: "background-color var(--motion-duration-3) var(--motion-easing-standard)", userSelect: "none" }}>
@@ -244,13 +255,29 @@ export function SideNavItem({
244
255
  {!isChild && item.icon && (
245
256
  <div style={{ width: L.iconWrap, height: L.iconWrap, display: "flex",
246
257
  alignItems: "center", justifyContent: "center", flexShrink: 0,
247
- marginLeft: L.rowPadH, color: iconColor }}>
258
+ // COLLAPSED CENTRES, EXPANDED INDENTS. The fixed 12px left margin
259
+ // applied in both states, so on the rail the 24px icon sat at
260
+ // x 16..40 of the 44 square: 6px right of centre, in every state.
261
+ // Reported 2026-10-02. Auto margins hand the free space back to
262
+ // both sides, which with the 6px right padding above reproduces
263
+ // Figma's x=9 exactly.
264
+ marginLeft: isSidebarCollapsed ? "auto" : L.rowPadH,
265
+ marginRight: isSidebarCollapsed ? "auto" : undefined,
266
+ color: iconColor }}>
248
267
  {typeof item.icon === "function"
249
268
  ? item.icon({ size: L.iconInner, color: iconColor })
250
269
  : typeof item.icon === "string"
251
270
  ? <span className="material-symbols-rounded" aria-hidden="true"
252
271
  style={{ fontSize: L.iconInner, lineHeight: 1, color: iconColor,
253
- fontVariationSettings: "'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 20" }}>
272
+ // display:block so the glyph is laid out as a box rather than
273
+ // on a text baseline — an inline glyph in a flex-centred
274
+ // parent is centred by its line box, not by its own art, so
275
+ // it rode high inside the 24px wrap.
276
+ display: "block",
277
+ // opsz MUST match fontSize. It said 20 against a 16px size,
278
+ // so the glyph was drawn on a 20px grid and scaled down into
279
+ // a 16px box, which shifts the art off centre.
280
+ fontVariationSettings: `'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' ${L.iconInner}` }}>
254
281
  {item.icon}
255
282
  </span>
256
283
  : React.cloneElement(item.icon, { style: { color: iconColor } })}
@@ -258,9 +285,19 @@ export function SideNavItem({
258
285
  )}
259
286
 
260
287
  {/* Label */}
261
- <div style={{ flex: 1, minWidth: 0,
262
- paddingLeft: isChild ? 32 : L.textPad,
263
- paddingRight: (!isChild && hasChildren) ? 0 : L.rowPadH,
288
+ <div style={{
289
+ // Collapsed, the label must take NO part in the flex distribution.
290
+ // With flex:1 it still claimed the free space even though max-width
291
+ // clamped it to zero, so the icon's auto margins had nothing left to
292
+ // centre with and the icon stayed hard left.
293
+ flex: isSidebarCollapsed ? "0 0 0px" : 1,
294
+ minWidth: 0,
295
+ // Collapsed, the padding has to go too. max-width clamps the CONTENT
296
+ // box, so the label still occupied 8px of padding on the rail and ate
297
+ // most of the free space the icon's auto margins needed: the icon
298
+ // landed at x=5 instead of Figma's x=9.
299
+ paddingLeft: isSidebarCollapsed ? 0 : (isChild ? 32 : L.textPad),
300
+ paddingRight: isSidebarCollapsed ? 0 : ((!isChild && hasChildren) ? 0 : L.rowPadH),
264
301
  maxWidth: isSidebarCollapsed ? 0 : 200,
265
302
  opacity: isSidebarCollapsed ? 0 : 1,
266
303
  overflow: "hidden",
@@ -276,7 +313,7 @@ export function SideNavItem({
276
313
 
277
314
  {/* Chevron — groupers only */}
278
315
  {!isChild && hasChildren && (
279
- <div style={{ width: 40, height: L.iconWrap, display: "flex",
316
+ <div style={{ width: isSidebarCollapsed ? 0 : 40, height: L.iconWrap, display: "flex",
280
317
  alignItems: "center", justifyContent: "center", flexShrink: 0,
281
318
  maxWidth: isSidebarCollapsed ? 0 : 40,
282
319
  opacity: isSidebarCollapsed ? 0 : 1,
package/dist/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  **The colour contract is 210 names.** Your full working vocabulary is
4
4
  **360**. If you add up every declaration in this folder you get
5
- 1152. That number is not the contract, and the table below says why.
5
+ 1155. That number is not the contract, and the table below says why.
6
6
 
7
7
  ## Link these, in this order
8
8
 
@@ -30,7 +30,7 @@ error**.
30
30
  | `themes/midnight.css` | 210 | yes | yes | Colour contract, Midnight Mode. Same names as light. |
31
31
  | `type.css` | 39 | yes | yes | Type scale. Compose from these. |
32
32
  | `layout.css` | 76 | yes | yes | Spacing, radii, border widths. |
33
- | `layout-contextual.css` | 34 | **no** | **no** | Per-component metrics. This repo's components use these. |
33
+ | `layout-contextual.css` | 37 | **no** | **no** | Per-component metrics. This repo's components use these. |
34
34
  | `motion.css` | 21 | yes | yes | Durations and easings. |
35
35
  | `layout-responsive.css` | 9 | yes | yes | Sheet and TopNav padding. The only layout tokens with media queries. |
36
36
  | `breakpoints.css` | 5 | yes | yes | Breakpoint values. |
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "$comment": "The names a consumer may use. Generated from the emitted CSS by scripts/build-contract.js, do not hand-edit. Lint against `contract` if you want the boundary enforced; nothing here blocks a primitive.",
3
- "version": "11.0.0",
3
+ "version": "11.1.0",
4
4
  "generated": "2026-10-02",
5
5
  "counts": {
6
6
  "contract": 360,
7
- "infrastructure": 582,
8
- "declarationsAcrossAllFiles": 1152
7
+ "infrastructure": 585,
8
+ "declarationsAcrossAllFiles": 1155
9
9
  },
10
10
  "loadOrder": [
11
11
  "primitives.css",
@@ -51,7 +51,7 @@
51
51
  "layout-contextual.css": {
52
52
  "contract": false,
53
53
  "mustLoad": false,
54
- "count": 34,
54
+ "count": 37,
55
55
  "role": "Per-component metrics. This repo's components use these."
56
56
  },
57
57
  "motion.css": {
@@ -9,7 +9,7 @@
9
9
  prefer layout.css, which is the general spacing contract. These exist so a
10
10
  component's geometry can be tuned without moving the whole scale.
11
11
 
12
- Declares 34 custom properties.
12
+ Declares 37 custom properties.
13
13
  Generated — do not edit. Run `npm run build-tokens`.
14
14
  ==========================================================================
15
15
  */
@@ -48,4 +48,7 @@
48
48
  --contextual-layout-units-sidenav-width-collapsed: 84px;
49
49
  --contextual-layout-units-sidenav-width-expanded: 256px;
50
50
  --contextual-layout-units-topnav-height: 60px;
51
+ --contextual-layout-units-widget-minwidth-detail: 515px;
52
+ --contextual-layout-units-widget-minwidth-explore: 1050px;
53
+ --contextual-layout-units-widget-minwidth-glance: 275px;
51
54
  }
package/dist/tokens.js CHANGED
@@ -413,6 +413,39 @@ const tokens = {
413
413
  "height"
414
414
  ]
415
415
  },
416
+ "contextual-layout-units-widget-minwidth-glance": {
417
+ "value": 275,
418
+ "type": "number",
419
+ "path": [
420
+ "contextual-layout-units",
421
+ "amplify",
422
+ "widget",
423
+ "minwidth",
424
+ "glance"
425
+ ]
426
+ },
427
+ "contextual-layout-units-widget-minwidth-detail": {
428
+ "value": 515,
429
+ "type": "number",
430
+ "path": [
431
+ "contextual-layout-units",
432
+ "amplify",
433
+ "widget",
434
+ "minwidth",
435
+ "detail"
436
+ ]
437
+ },
438
+ "contextual-layout-units-widget-minwidth-explore": {
439
+ "value": 1050,
440
+ "type": "number",
441
+ "path": [
442
+ "contextual-layout-units",
443
+ "amplify",
444
+ "widget",
445
+ "minwidth",
446
+ "explore"
447
+ ]
448
+ },
416
449
  "elevation-light-lift": {
417
450
  "value": "0 10px 28px -6px rgba(24,27,43,0.08)",
418
451
  "type": "string",
package/dist/tokens.json CHANGED
@@ -202,6 +202,22 @@
202
202
  "$type": "number",
203
203
  "$value": "{primitive-unit.unit.60}"
204
204
  }
205
+ },
206
+ "widget": {
207
+ "minwidth": {
208
+ "glance": {
209
+ "$type": "number",
210
+ "$value": 275
211
+ },
212
+ "detail": {
213
+ "$type": "number",
214
+ "$value": 515
215
+ },
216
+ "explore": {
217
+ "$type": "number",
218
+ "$value": 1050
219
+ }
220
+ }
205
221
  }
206
222
  },
207
223
  "newco": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@helloimjolopez-pathway/pathway-tokens",
3
- "version": "11.0.0",
3
+ "version": "11.1.0",
4
4
  "description": "Pathway Design System tokens — CSS custom properties, JS export, and DTCG JSON",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
@@ -63,7 +63,7 @@
63
63
  "fix-tokens-preview": "node scripts/fix-tokens.js --dry-run",
64
64
  "build-tokens": "node scripts/sync-motion-tokens.js && node style-dictionary.config.js && node scripts/stamp-headers.js",
65
65
  "build-dist": "node scripts/sync-motion-tokens.js && node style-dictionary.config.js && node scripts/stamp-headers.js && node scripts/check-demo-tokens.js && node scripts/check-token-refs.js && node scripts/check-token-names.js && node scripts/check-token-object-refs.js && node scripts/fix-stale-doc-hex.js --check && node scripts/check-state-distinctness.js && node scripts/check-ladder-order.js && node scripts/check-variant-distinctness.js && node scripts/check-fill-foreground-pairs.js && node scripts/check-story-yield.js && node scripts/check-motion-coverage.js && node scripts/build-dist.js && node scripts/build-index.js && node scripts/build-contract.js && npm run build-elements && npm run sync-demo-module-icon",
66
- "storybook": "node style-dictionary.config.js && storybook dev -p 6006",
66
+ "storybook": "node style-dictionary.config.js && PATHWAY_BRAND_AXIS=1 storybook dev -p 6006",
67
67
  "build-storybook": "storybook build",
68
68
  "check-demo-tokens": "node scripts/check-demo-tokens.js",
69
69
  "assemble-export": "node scripts/assemble-figma-export.js",
@@ -84,7 +84,8 @@
84
84
  "check-doc-hex": "node scripts/fix-stale-doc-hex.js --check",
85
85
  "check-token-object-refs": "node scripts/check-token-object-refs.js",
86
86
  "check-motion-coverage": "node scripts/check-motion-coverage.js",
87
- "sync-demo-module-icon": "node scripts/sync-demo-module-icon.js"
87
+ "sync-demo-module-icon": "node scripts/sync-demo-module-icon.js",
88
+ "build-storybook:brands": "PATHWAY_BRAND_AXIS=1 storybook build"
88
89
  },
89
90
  "devDependencies": {
90
91
  "@babel/preset-env": "^7.29.2",