@godxjp/ui 28.13.0 → 30.0.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.
Files changed (164) hide show
  1. package/agent/START-HERE.md +29 -10
  2. package/agent/components/Anchor.json +6 -1
  3. package/agent/components/AppShell.json +1 -1
  4. package/agent/components/AreaChart.json +19 -1
  5. package/agent/components/BarChart.json +11 -1
  6. package/agent/components/Cascader.json +1 -1
  7. package/agent/components/CompactBarTrend.json +1 -1
  8. package/agent/components/DataState.json +1 -1
  9. package/agent/components/DataTable.json +4 -4
  10. package/agent/components/FormField.json +1 -1
  11. package/agent/components/InfiniteQueryState.json +1 -1
  12. package/agent/components/Input.json +1 -1
  13. package/agent/components/LineChart.json +20 -2
  14. package/agent/components/ListRow.json +1 -1
  15. package/agent/components/Masonry.json +1 -1
  16. package/agent/components/MasterDetail.json +1 -1
  17. package/agent/components/PasswordStrength.json +1 -1
  18. package/agent/components/PermissionMatrix.json +1 -1
  19. package/agent/components/Select.json +1 -0
  20. package/agent/components/Sidebar.json +1 -1
  21. package/agent/components/Table.json +8 -3
  22. package/agent/components/ThemeScope.json +49 -0
  23. package/agent/components/Topbar.json +1 -0
  24. package/agent/components/TopbarItem.json +2 -1
  25. package/agent/components/Transfer.json +1 -1
  26. package/agent/components/TreeSelect.json +1 -1
  27. package/agent/components/UploadCropDialog.json +1 -1
  28. package/agent/components/formatDate.json +1 -1
  29. package/agent/components-index.json +5 -0
  30. package/agent/components.json +138 -30
  31. package/agent/index.json +19 -9
  32. package/agent/llms.txt +10 -10
  33. package/agent/patterns/tenant-brand-color.json +28 -0
  34. package/agent/patterns-index.json +27 -0
  35. package/agent/patterns.json +28 -0
  36. package/agent/rules.json +15 -0
  37. package/agent/tokens.json +5055 -1060
  38. package/dist/app/index.d.ts +3 -0
  39. package/dist/app/index.js +3 -0
  40. package/dist/app/tenant-theme.d.ts +80 -0
  41. package/dist/app/tenant-theme.js +154 -0
  42. package/dist/app/theme-axes.d.ts +14 -1
  43. package/dist/app/theme-axes.js +24 -31
  44. package/dist/components/charts/chart-cartesian.d.ts +5 -1
  45. package/dist/components/charts/chart-cartesian.js +15 -8
  46. package/dist/components/data-display/badge.d.ts +1 -1
  47. package/dist/components/data-display/badge.js +21 -3
  48. package/dist/components/data-display/carousel.js +4 -4
  49. package/dist/components/data-display/data-table.js +13 -2
  50. package/dist/components/data-display/permission-matrix.js +1 -1
  51. package/dist/components/data-display/table.d.ts +11 -2
  52. package/dist/components/data-display/table.js +19 -3
  53. package/dist/components/data-entry/control-appearance.d.ts +12 -6
  54. package/dist/components/data-entry/control-appearance.js +1 -1
  55. package/dist/components/data-entry/select.js +4 -3
  56. package/dist/components/feedback/dialog.js +6 -3
  57. package/dist/components/feedback/overlay-header-tone.d.ts +7 -0
  58. package/dist/components/feedback/overlay-header-tone.js +4 -4
  59. package/dist/components/feedback/sheet.d.ts +1 -1
  60. package/dist/components/feedback/sheet.js +6 -9
  61. package/dist/components/feedback/sonner.js +16 -3
  62. package/dist/components/general/button.js +22 -5
  63. package/dist/components/layout/affix.js +15 -1
  64. package/dist/components/layout/sidebar.js +7 -1
  65. package/dist/components/navigation/anchor.d.ts +1 -1
  66. package/dist/components/navigation/anchor.js +5 -4
  67. package/dist/components/navigation/app-setting-picker.js +1 -1
  68. package/dist/components/navigation/pagination.js +1 -1
  69. package/dist/components/navigation/tabs.js +15 -2
  70. package/dist/components/query/infinite-query-state.d.ts +22 -6
  71. package/dist/contracts/measurement.json +1 -1
  72. package/dist/lib/control-styles.d.ts +31 -11
  73. package/dist/lib/control-styles.js +6 -6
  74. package/dist/lib/overlay-portal.d.ts +20 -0
  75. package/dist/lib/overlay-portal.js +93 -0
  76. package/dist/props/components/app.prop.d.ts +12 -0
  77. package/dist/props/components/charts.prop.d.ts +30 -0
  78. package/dist/props/components/index.d.ts +1 -1
  79. package/dist/props/components/navigation.prop.d.ts +21 -2
  80. package/dist/props/components/query.prop.d.ts +36 -2
  81. package/dist/props/registry.d.ts +46 -1
  82. package/dist/props/registry.js +38 -3
  83. package/dist/styles/alert-layout.css +39 -19
  84. package/dist/styles/badge-layout.css +11 -7
  85. package/dist/styles/base.css +14 -5
  86. package/dist/styles/card-layout.css +29 -16
  87. package/dist/styles/chart-layout.css +27 -5
  88. package/dist/styles/control.css +225 -103
  89. package/dist/styles/data-display-layout.css +178 -76
  90. package/dist/styles/data-entry-layout.css +35 -99
  91. package/dist/styles/dialog-layout.css +58 -28
  92. package/dist/styles/float-button-layout.css +5 -5
  93. package/dist/styles/focus-ring.css +11 -7
  94. package/dist/styles/layout.css +53 -25
  95. package/dist/styles/logo-layout.css +3 -3
  96. package/dist/styles/motion.css +2 -2
  97. package/dist/styles/navigation-layout.css +117 -44
  98. package/dist/styles/shell-layout.css +90 -124
  99. package/dist/styles/table-layout.css +66 -24
  100. package/dist/styles/text-layout.css +13 -4
  101. package/dist/styles/toggle.css +9 -3
  102. package/dist/tokens/components/actions.css +1 -1
  103. package/dist/tokens/components/attachments.css +4 -4
  104. package/dist/tokens/components/badge.css +4 -4
  105. package/dist/tokens/components/banner.css +1 -1
  106. package/dist/tokens/components/callout.css +1 -1
  107. package/dist/tokens/components/card.css +13 -8
  108. package/dist/tokens/components/chart.css +11 -2
  109. package/dist/tokens/components/chat-bubble.css +2 -2
  110. package/dist/tokens/components/control.css +41 -22
  111. package/dist/tokens/components/conversations.css +2 -1
  112. package/dist/tokens/components/data-display.css +23 -18
  113. package/dist/tokens/components/data-entry.css +1 -1
  114. package/dist/tokens/components/descriptions.css +2 -2
  115. package/dist/tokens/components/draggable-panel.css +2 -2
  116. package/dist/tokens/components/feedback.css +29 -9
  117. package/dist/tokens/components/float-button.css +1 -1
  118. package/dist/tokens/components/legal-document.css +2 -2
  119. package/dist/tokens/components/logo.css +2 -2
  120. package/dist/tokens/components/mega-menu.css +6 -4
  121. package/dist/tokens/components/navigation.css +27 -13
  122. package/dist/tokens/components/segmented.css +11 -6
  123. package/dist/tokens/components/separator.css +1 -1
  124. package/dist/tokens/components/shell.css +24 -10
  125. package/dist/tokens/components/table.css +13 -5
  126. package/dist/tokens/components/thought-chain.css +2 -2
  127. package/dist/tokens/components/toggle.css +3 -1
  128. package/dist/tokens/components/tree.css +3 -1
  129. package/dist/tokens/components/upload.css +8 -8
  130. package/dist/tokens/components/welcome.css +1 -1
  131. package/dist/tokens/foundation.css +30 -3
  132. package/docs/COMPOSITION-VS-COMPONENT.md +31 -0
  133. package/docs/CUSTOMER-THEMING.md +637 -1
  134. package/docs/FRAME-COVERAGE-REPORT.md +3 -2
  135. package/docs/GLASSMORPHISM-STANDARD.md +196 -0
  136. package/docs/THEME-API-COVERAGE.md +538 -0
  137. package/docs/TOKEN-RESOLUTION.md +195 -0
  138. package/docs/TOKENS.md +63 -24
  139. package/docs/asset-modules.d.ts +7 -0
  140. package/docs/data-display/charts.tsx +80 -0
  141. package/docs/data-display/data-table/index.tsx +30 -0
  142. package/docs/data-display/popover.tsx +1 -1
  143. package/docs/data-display/table.tsx +52 -0
  144. package/docs/feedback/sheet.tsx +10 -10
  145. package/docs/foundation/density.tsx +4 -4
  146. package/docs/i18n/messages/en.json +506 -0
  147. package/docs/i18n/messages/ja.json +506 -0
  148. package/docs/i18n/messages/vi.json +506 -0
  149. package/docs/layout/account-chip.tsx +2 -2
  150. package/docs/layout/responsive-grid.tsx +1 -1
  151. package/docs/navigation/toolbar.tsx +20 -12
  152. package/docs/providers/theme-scope.tsx +186 -0
  153. package/docs/showcase/caimono-price-comparison.tsx +911 -0
  154. package/docs/showcase/case4-login.tsx +2 -2
  155. package/docs/showcase/permission-matrix.tsx +13 -5
  156. package/docs/showcase/table-pagination.tsx +2 -1
  157. package/docs/showcase/tenant-brand-color.tsx +338 -0
  158. package/docs/showcase/theme-lab.tsx +2125 -0
  159. package/docs/themes/flat.css +462 -0
  160. package/docs/themes/glassmorphism.css +958 -0
  161. package/docs/themes/index.ts +219 -0
  162. package/docs/themes/neubrutalism.css +475 -0
  163. package/package.json +4 -3
  164. package/scripts/explain-token.mjs +382 -0
@@ -0,0 +1,475 @@
1
+ /**
2
+ * neubrutalism theme — the FOURTH theme, and the one chosen to break the token model rather than
3
+ * to flatter it.
4
+ *
5
+ * Reference: https://neubrutalism.com/. The style is defined by four moves, and they were picked
6
+ * for this lab because three of them are things no theme here had asked the API for before:
7
+ *
8
+ * 1. square corners — `flat.css` already proved this one, at 68 declarations
9
+ * 2. THICK BLACK BORDERS — new axis: nothing had tried to change a stroke WIDTH
10
+ * 3. HARD OFFSET SHADOWS — new: a shadow with no blur and full alpha, used as structure
11
+ * 4. SATURATED OPAQUE FILLS — the exact opposite of `glassmorphism.css`
12
+ *
13
+ * SAME CONSTRAINT AS `flat.css` AND `glassmorphism.css`, no exceptions: every line below is a
14
+ * `--custom-property` declaration under `[data-theme-style="neubrutalism"]`. No `border:`, no
15
+ * `box-shadow:`, no `border-radius:`, no selector into a `.ui-*` class. Where the look cannot be
16
+ * expressed that way the RESULT is the finding — `measure-glass.mjs` says which, not this comment.
17
+ *
18
+ * ── FINDING A · the `:root` freeze is not a radius quirk, it runs on the STROKE axis too ──────
19
+ * `flat.css` FINDING 1 records that squaring the corners costs 68 declarations because `--radius`,
20
+ * its six derived steps and 61 component mirrors are all `:root`-bound. Thickening the borders is
21
+ * the same shape on a different scale, and finding it a second time is what makes it a PROPERTY of
22
+ * the token model rather than an accident of one family:
23
+ *
24
+ * `--stroke-hairline … --stroke-2xl` is a real six-step foundation scale (foundation.css:814-819)
25
+ * and 44 component knobs read it as `--x: var(--stroke-y)`. Every one of those 44 is declared at
26
+ * `:root`, so it substitutes against the ROOT's `--stroke-hairline` and inherits the frozen 1px
27
+ * into this scope no matter what the scale says here.
28
+ *
29
+ * So the scale is restated AND the mirrors are restated, exactly as the radius family needs both.
30
+ *
31
+ * ── FINDING B · and under the mirrors, 107 border widths that are not tokens at all ───────────
32
+ * The 44 stroke mirrors are the reachable part. Counted across `src/styles/*.css` and
33
+ * `src/tokens/components/*.css`:
34
+ *
35
+ * 107 literal border widths — `border: 1px solid hsl(var(--border))` and friends
36
+ *
37
+ * The COLOUR in those rules is a token; the WIDTH beside it is a literal. That asymmetry is the
38
+ * finding: a theme can recolour every border in the library and cannot thicken most of them, so
39
+ * the single most defining property of this style is the one the API reaches least. Nothing is
40
+ * worked around here — the thick borders below land where a token exists and nowhere else, and
41
+ * the measurement is what shows which those are.
42
+ *
43
+ * ── FINDING C · shadows came through, and gh#880 is why ───────────────────────────────────────
44
+ * This theme needs a shadow that is pure structure — no blur, full alpha, hard offset — which is
45
+ * the furthest thing from what the six foundation steps ship. It works, in one restatement each,
46
+ * because gh#880 turned `--card-shadow` / `--sheet-shadow` / `--popover-shadow` / `--tooltip-shadow`
47
+ * / `--segmented-item-selected-shadow` into `initial` knobs that read the foundation step at the
48
+ * CALL site instead of freezing it at `:root`. Five mirrors are still frozen `var(--shadow-*)`
49
+ * bindings and take one line each, and they are listed as such.
50
+ *
51
+ * That contrast is the useful part: the shadow family was fixed and the stroke family was not, so
52
+ * this file shows the same model succeeding and failing on two axes at once. The fix shape is
53
+ * known and it is `initial`.
54
+ *
55
+ * ── FINDING D · this theme does not need gh#887's ink walk, and that is a result, not luck ────
56
+ * `flat.css` FINDING 1b records that seed-derived navigation ink fails AA at both ends of the seed
57
+ * range on a light canvas. Neubrutalism sidesteps it by construction: the seed paints FILLS, never
58
+ * ink. Every string on this theme is near-black on a light fill or near-white on a dark one, so
59
+ * the brand colour never has to carry a contrast contract. It is worth writing down because it is
60
+ * the cheapest known answer to gh#887 — not "derive safer ink", but "do not use the seed as ink" —
61
+ * and it costs the theme nothing it wanted.
62
+ *
63
+ * ── FINDING E · no translucency, so no fallback is owed ───────────────────────────────────────
64
+ * docs/TOKEN-RESOLUTION.md §5 puts `prefers-reduced-transparency` and `@supports not
65
+ * (backdrop-filter)` on the theme that made a surface translucent. Every alpha below is 100% and
66
+ * no blur knob is turned on. The absence is the proof, same as `flat.css` FINDING 4.
67
+ */
68
+ [data-theme-style="neubrutalism"] {
69
+ /* ── Corners. Same 68 declarations `flat.css` FINDING 1 costs, for the same reason:
70
+ * `--radius` and its six steps are `:root`-bound and so are 61 component mirrors, so
71
+ * one design decision is 68 lines in every theme that makes it. List generated, not
72
+ * hand-kept — see the docblock. ───────────────────────────────────────────────────── */
73
+ --radius: 0;
74
+ --radius-xs: 0;
75
+ --radius-sm: 0;
76
+ --radius-md: 0;
77
+ --radius-lg: 0;
78
+ --radius-xl: 0;
79
+ --radius-2xl: 0;
80
+
81
+ --actions-radius: 0;
82
+ --app-launcher-launchpad-mark-radius: 0;
83
+ --app-launcher-launchpad-tile-radius: 0;
84
+ --app-launcher-mark-radius: 0;
85
+ --app-launcher-tile-radius: 0;
86
+ --attachments-card-radius: 0;
87
+ --avatar-square-radius: 0;
88
+ --badge-radius: 0;
89
+ --button-radius: 0;
90
+ --calendar-day-radius: 0;
91
+ --calendar-weekday-radius: 0;
92
+ --card-radius: 0;
93
+ --card-service-launcher-icon-radius: 0;
94
+ --cascader-result-radius: 0;
95
+ --chart-trend-bar-radius: 0;
96
+ --chat-bubble-radius: 0;
97
+ --code-block-radius: 0;
98
+ --control-affix-action-radius: 0;
99
+ --control-radius: 0;
100
+ --conversations-item-radius: 0;
101
+ --descriptions-border-radius: 0;
102
+ --draggable-panel-radius: 0;
103
+ --float-button-group-radius: 0;
104
+ --legal-document-toc-item-radius: 0;
105
+ --logo-radius: 0;
106
+ --mega-menu-link-radius: 0;
107
+ --mega-menu-panel-radius: 0;
108
+ --mega-menu-trigger-radius: 0;
109
+ --menu-item-radius: 0;
110
+ --popover-radius: 0;
111
+ --progress-breakdown-radius: 0;
112
+ --prose-code-radius: 0;
113
+ --prose-image-radius: 0;
114
+ --radius: 0;
115
+ --radius-2xl: 0;
116
+ --radius-lg: 0;
117
+ --radius-md: 0;
118
+ --radius-sm: 0;
119
+ --radius-xl: 0;
120
+ --radius-xs: 0;
121
+ --segmented-item-radius: 0;
122
+ --segmented-track-radius: 0;
123
+ --skeleton-element-radius: 0;
124
+ --skeleton-radius: 0;
125
+ --slider-tooltip-radius: 0;
126
+ --stat-card-icon-radius: 0;
127
+ --steps-nav-radius: 0;
128
+ --table-skeleton-radius: 0;
129
+ --tabs-add-radius: 0;
130
+ --tabs-card-radius: 0;
131
+ --tabs-overflow-radius: 0;
132
+ --tabs-tab-remove-radius: 0;
133
+ --thought-chain-item-radius: 0;
134
+ --thumbnail-radius: 0;
135
+ --time-picker-option-radius: 0;
136
+ --timeline-grid-event-radius: 0;
137
+ --tooltip-radius: 0;
138
+ --transfer-pane-radius: 0;
139
+ --transfer-row-radius: 0;
140
+ --tree-node-radius: 0;
141
+ --tree-select-row-radius: 0;
142
+ --upload-draft-radius: 0;
143
+ --upload-dropzone-radius: 0;
144
+ --upload-picture-badge-radius: 0;
145
+ --upload-picture-radius: 0;
146
+ --upload-row-radius: 0;
147
+ --upload-tile-radius: 0;
148
+ --welcome-radius: 0;
149
+
150
+ /* ── THE STROKE SCALE, and the second axis the `:root` freeze runs on. ─────────────────────
151
+ * `--stroke-hairline … --stroke-2xl` is a real foundation scale (foundation.css:814-819) and
152
+ * 44 component knobs read it. Restating the scale here reaches only the rules that read
153
+ * `var(--stroke-*)` DIRECTLY; the 44 knobs are `--x: var(--stroke-y)` declared at `:root`, so
154
+ * they froze against the root's values exactly as the radius family does. Both halves are
155
+ * below, and `measure-glass.mjs` is what says which of them moved. */
156
+ --stroke-hairline: 3px;
157
+ --stroke-sm: 3px;
158
+ --stroke-md: 4px;
159
+ --stroke-lg: 5px;
160
+ --stroke-xl: 6px;
161
+ --stroke-2xl: 8px;
162
+
163
+ /* The 22 frozen EDGE mirrors this theme used to restate are GONE (gh#906): they are `initial`
164
+ * knobs now and read the stroke scale above at their call sites, so the six lines above are the
165
+ * whole of it. Deleting them and measuring 563/563 unchanged is the acceptance test that issue
166
+ * asked for. The other 21 stroke mirrors are a caret, a bar size, a progress ring or a tone rail
167
+ * — reachable now too, and deliberately left at their own steps, because thickening those would
168
+ * change what they MEAN (`flat.css` FINDING 2, on this axis). */
169
+
170
+ /* ── SHADOWS AS STRUCTURE. No blur, full alpha, hard offset — the move that makes the style
171
+ * read as "pasted paper". The six foundation steps are restated; five frozen mirrors follow
172
+ * (FINDING C). `--shadow-color` is already `0 0 0`, so `rgb(var(--shadow-color))` at no alpha
173
+ * is the pure black this needs. ─────────────────────────────────────────────────────────── */
174
+ --shadow-xs: 2px 2px 0 rgb(var(--shadow-color));
175
+ --shadow-sm: 3px 3px 0 rgb(var(--shadow-color));
176
+ --shadow-md: 4px 4px 0 rgb(var(--shadow-color));
177
+ --shadow-lg: 6px 6px 0 rgb(var(--shadow-color));
178
+ --shadow-xl: 8px 8px 0 rgb(var(--shadow-color));
179
+ --shadow-2xl: 12px 12px 0 rgb(var(--shadow-color));
180
+
181
+ --app-launcher-launchpad-mark-shadow: 4px 4px 0 rgb(var(--shadow-color));
182
+ --card-hover-shadow: 8px 8px 0 rgb(var(--shadow-color));
183
+ --control-shadow: 3px 3px 0 rgb(var(--shadow-color));
184
+ --draggable-panel-shadow: 6px 6px 0 rgb(var(--shadow-color));
185
+ --float-button-shadow: 6px 6px 0 rgb(var(--shadow-color));
186
+ --mega-menu-panel-shadow: 6px 6px 0 rgb(var(--shadow-color));
187
+
188
+ /* ── SURFACES. Opaque paper, pure-black edges. The border is doing the work a shadow does in
189
+ * the default theme and a blur does in glass, so it is pure black rather than a hairline
190
+ * grey — at anything lighter the style stops reading. ─────────────────────────────────── */
191
+ --card-background: 0 0% 100%;
192
+ --card: 0 0% 100%;
193
+ --popover: 0 0% 100%;
194
+ --border: 0 0% 0%;
195
+ --input: 0 0% 0%;
196
+
197
+ /* ── INK. Near-black throughout. Solved against `--accent`, the DARKEST fill this theme
198
+ * declares (the worst case for a dark ink), using the same sRGB relative-luminance formula
199
+ * `measure-glass.mjs` uses. Worst case is the seed-tinted `--accent` at L 88%, whose darkest
200
+ * realisation across the five SEEDS is a blue hue at luminance 0.572:
201
+ * --foreground 0% → 15.9:1 --muted-foreground 18% → 8.06:1
202
+ * --text-tertiary 26% → 5.95:1 brand ink 16% → 5.91:1
203
+ * All clear the 4.5:1 text floor; on `--card` (white) every one is higher. ─────────────── */
204
+ --foreground: 0 0% 0%;
205
+ --card-foreground: 0 0% 0%;
206
+ --popover-foreground: 0 0% 0%;
207
+ --muted-foreground: 0 0% 18%;
208
+ --text-tertiary: 0 0% 26%;
209
+
210
+ /* ── FILLS. Literal fallbacks; the `@supports` block below re-derives all four from the seed.
211
+ * Saturated and LIGHT, because FINDING D depends on it: black ink on a light fill needs no
212
+ * contrast contract, so the seed can be as loud as the style wants. ───────────────────── */
213
+ --background: 48 100% 95%;
214
+ --muted: 48 60% 90%;
215
+ --accent: 48 90% 88%;
216
+ --secondary: 48 80% 90%;
217
+ --app-shell-main-background: hsl(48 100% 95%);
218
+
219
+ /* ── BRAND INK. Hue from the seed, lightness clamped (FINDING D): these roles exist, so they
220
+ * are set rather than left to the seed walk, but nothing in this theme relies on them
221
+ * carrying the brand at a readable ratio. Same two value FORMS as `flat.css` — a token read
222
+ * inside `hsl()` takes a bare triplet, one read as a complete value takes a whole `hsl(...)`,
223
+ * and getting it backwards fails silently. ──────────────────────────────────────────────── */
224
+ --text-link: 48 90% 16%;
225
+ --text-brand: 48 90% 16%;
226
+ --text-primary: 48 90% 14%;
227
+ --anchor-ink-color: 48 90% 16%;
228
+ --auth-shell-divider-label-color: 0 0% 18%;
229
+ --org-switcher-meta-foreground: 0 0% 18%;
230
+ --separator-label-color: 0 0% 18%;
231
+ --sidebar-item-active-foreground: hsl(48 90% 14%);
232
+ --sidebar-nav-icon-active-foreground: hsl(48 90% 14%);
233
+ --mega-menu-trigger-current-foreground: hsl(48 90% 14%);
234
+ --mega-menu-trigger-open-foreground: hsl(48 90% 14%);
235
+ --mega-menu-link-current-foreground: hsl(48 90% 14%);
236
+ --timeline-grid-event-muted-color: hsl(0 0% 18%);
237
+
238
+ /* ── FOCUS. Pure black and THICK — the one place this style and WCAG 2.2 SC 2.4.11 want the
239
+ * same thing. Pinned off the brand for the reason `flat.css` gives: a ring that follows the
240
+ * seed is invisible for a `#FFD400` tenant. ───────────────────────────────────────────── */
241
+ --focus-ring-color: 0 0% 0%;
242
+ --focus-outline-color: 0 0% 0%;
243
+ --focus-ring-glow-color: 0 0% 0%;
244
+ --control-outline: 0 0% 0%;
245
+ --focus-ring-width: calc(3px * var(--focus-outline));
246
+ --region-focus-ring-color: hsl(0 0% 0%);
247
+
248
+ /* ── INTERACTION STATES. The canonical neubrutalism hover is the element pressing INTO its
249
+ * shadow — a transform, which no token expresses and which is therefore not attempted here.
250
+ * What is left is the fill, so a hover is a firmly DARKER step of the same seed rather than a
251
+ * wash: at this saturation a 4% step is invisible. The ink never drops its ratio to signal a
252
+ * state (docs/GLASSMORPHISM-STANDARD.md §3). ──────────────────────────────────────────── */
253
+ --topbar-item-hover-background: 48 90% 80%;
254
+ --topbar-item-hover-color: 0 0% 0%;
255
+ --segmented-item-hover-background: 48 90% 80%;
256
+ --segmented-item-hover-color: 0 0% 0%;
257
+ --segmented-item-active-background: 48 90% 72%;
258
+ --app-launcher-tile-hover-background: 48 90% 80%;
259
+ --app-launcher-tile-hover-color: 0 0% 0%;
260
+ --control-variant-filled-hover-background: 48 90% 80%;
261
+ --choice-button-selected-color: 0 0% 0%;
262
+ --choice-button-selected-border-color: 0 0% 0%;
263
+ --secondary-hover: 48 80% 80%;
264
+ --secondary-active: 48 80% 72%;
265
+
266
+ --menu-item-hover-background: hsl(48 90% 82%);
267
+ --menu-item-hover-foreground: hsl(0 0% 0%);
268
+ --table-row-hover-background: hsl(48 90% 86%);
269
+ --table-row-selected-background: hsl(48 90% 78%);
270
+ --tree-node-hover-background: hsl(48 90% 86%);
271
+ --tree-node-selected-background: hsl(48 90% 78%);
272
+ --tree-node-selected-foreground: hsl(0 0% 0%);
273
+ --mega-menu-trigger-hover-background: hsl(48 90% 82%);
274
+ --mega-menu-trigger-hover-foreground: hsl(0 0% 0%);
275
+ --mega-menu-link-hover-background: hsl(48 90% 82%);
276
+ --mega-menu-link-hover-foreground: hsl(0 0% 0%);
277
+ --sidebar-nav-item-hover-foreground: hsl(0 0% 0%);
278
+ --sidebar-nav-icon-hover-foreground: hsl(0 0% 0%);
279
+ --conversations-item-active-background: hsl(48 90% 78%);
280
+ --conversations-item-active-color: hsl(0 0% 0%);
281
+ --tabs-count-active-background: hsl(48 90% 74%);
282
+ --tabs-count-active-color: hsl(0 0% 0%);
283
+ --toggle-soft-hover-background: hsl(48 90% 84%);
284
+ --toggle-pressed-count-background: hsl(48 90% 74%);
285
+ --toggle-pressed-count-color: hsl(0 0% 0%);
286
+ --toggle-pressed-border-color: hsl(0 0% 0%);
287
+ --switch-unchecked-background: hsl(0 0% 72%);
288
+ --switch-content-unchecked-foreground: hsl(0 0% 12%);
289
+
290
+ --text-action-color: hsl(0 0% 0%);
291
+ --text-action-color-hover: hsl(0 0% 18%);
292
+ }
293
+
294
+ /* Seed-derived fills. The literals above stand where relative colour is unsupported. Only the
295
+ * HUE follows the seed — every lightness is pinned, because lightness is not luminance and one
296
+ * clamp cannot serve the hue circle (the number `flat.css` had to move twice). Solved with the
297
+ * sRGB formula against all five `SEEDS` from `docs/themes/index.ts`: worst case is the violet
298
+ * seed's `--accent`, where `--text-tertiary` reads 6.35:1. */
299
+ @supports (color: hsl(from red h s l)) {
300
+ [data-theme-style="neubrutalism"] {
301
+ --background: from hsl(var(--primary)) h 100% 95%;
302
+ --muted: from hsl(var(--primary)) h 60% 90%;
303
+ --accent: from hsl(var(--primary)) h 90% 88%;
304
+ --secondary: from hsl(var(--primary)) h 80% 90%;
305
+ --app-shell-main-background: hsl(from hsl(var(--primary)) h 100% 95%);
306
+
307
+ --text-link: from hsl(var(--primary)) h 90% 16%;
308
+ --text-brand: from hsl(var(--primary)) h 90% 16%;
309
+ --text-primary: from hsl(var(--primary)) h 90% 14%;
310
+ --anchor-ink-color: from hsl(var(--primary)) h 90% 16%;
311
+ --sidebar-item-active-foreground: hsl(from hsl(var(--primary)) h 90% 14%);
312
+ --sidebar-nav-icon-active-foreground: hsl(from hsl(var(--primary)) h 90% 14%);
313
+ --mega-menu-trigger-current-foreground: hsl(from hsl(var(--primary)) h 90% 14%);
314
+ --mega-menu-trigger-open-foreground: hsl(from hsl(var(--primary)) h 90% 14%);
315
+ --mega-menu-link-current-foreground: hsl(from hsl(var(--primary)) h 90% 14%);
316
+
317
+ --topbar-item-hover-background: from hsl(var(--primary)) h 90% 80%;
318
+ --segmented-item-hover-background: from hsl(var(--primary)) h 90% 80%;
319
+ --segmented-item-active-background: from hsl(var(--primary)) h 90% 72%;
320
+ --app-launcher-tile-hover-background: from hsl(var(--primary)) h 90% 80%;
321
+ --control-variant-filled-hover-background: from hsl(var(--primary)) h 90% 80%;
322
+ --secondary-hover: from hsl(var(--primary)) h 80% 80%;
323
+ --secondary-active: from hsl(var(--primary)) h 80% 72%;
324
+
325
+ --menu-item-hover-background: hsl(from hsl(var(--primary)) h 90% 82%);
326
+ --table-row-hover-background: hsl(from hsl(var(--primary)) h 90% 86%);
327
+ --table-row-selected-background: hsl(from hsl(var(--primary)) h 90% 78%);
328
+ --tree-node-hover-background: hsl(from hsl(var(--primary)) h 90% 86%);
329
+ --tree-node-selected-background: hsl(from hsl(var(--primary)) h 90% 78%);
330
+ --mega-menu-trigger-hover-background: hsl(from hsl(var(--primary)) h 90% 82%);
331
+ --mega-menu-link-hover-background: hsl(from hsl(var(--primary)) h 90% 82%);
332
+ --conversations-item-active-background: hsl(from hsl(var(--primary)) h 90% 78%);
333
+ --tabs-count-active-background: hsl(from hsl(var(--primary)) h 90% 74%);
334
+ --toggle-soft-hover-background: hsl(from hsl(var(--primary)) h 90% 84%);
335
+ --toggle-pressed-count-background: hsl(from hsl(var(--primary)) h 90% 74%);
336
+ }
337
+ }
338
+
339
+ /**
340
+ * The dark polarity. Same gh#896 shape as `flat.css` FINDING 5 and the same fix: the selector
341
+ * pair mirrors the library's own `.dark, :root[data-theme="dark"]` so this is the SAME div matched
342
+ * at (0,2,0), beating the base rule's (0,1,0) on every property it restates — and leaving the 68
343
+ * radius lines, the 22 stroke lines and the shadow geometry flowing from the base rule untouched,
344
+ * because the cascade resolves per PROPERTY, not per rule.
345
+ *
346
+ * `--shadow-color` inverts to white. A hard black shadow on a black canvas is not a subtle shadow,
347
+ * it is no shadow — the offset is the whole device here, so it has to be the thing the canvas is
348
+ * not. This is the one token in the file whose DARK value is not a lightness step of its light
349
+ * value, and it is why the shadow family being themeable (FINDING C) mattered twice over.
350
+ *
351
+ * Ink solved against `--accent` again — in dark it is the LIGHTEST fill and so the worst case for
352
+ * a light ink, the inverse of the light block. Across all five seeds the worst is the citron
353
+ * seed: `--text-tertiary` 4.84:1, `--muted-foreground` 5.90:1, `--foreground` 7.77:1.
354
+ */
355
+ .dark [data-theme-style="neubrutalism"],
356
+ [data-theme="dark"] [data-theme-style="neubrutalism"] {
357
+ --shadow-color: 255 255 255;
358
+
359
+ --card-background: 0 0% 14%;
360
+ --card: 0 0% 14%;
361
+ --popover: 0 0% 14%;
362
+ --border: 0 0% 100%;
363
+ --input: 0 0% 100%;
364
+
365
+ --foreground: 0 0% 100%;
366
+ --card-foreground: 0 0% 100%;
367
+ --popover-foreground: 0 0% 100%;
368
+ --muted-foreground: 0 0% 88%;
369
+ --text-tertiary: 0 0% 80%;
370
+
371
+ --background: 0 0% 8%;
372
+ --muted: 48 60% 16%;
373
+ --accent: 48 90% 20%;
374
+ --secondary: 48 80% 18%;
375
+ --app-shell-main-background: hsl(0 0% 8%);
376
+
377
+ --text-link: 48 90% 86%;
378
+ --text-brand: 48 90% 86%;
379
+ --text-primary: 48 90% 90%;
380
+ --anchor-ink-color: 48 90% 86%;
381
+ --auth-shell-divider-label-color: 0 0% 88%;
382
+ --org-switcher-meta-foreground: 0 0% 88%;
383
+ --separator-label-color: 0 0% 88%;
384
+ --sidebar-item-active-foreground: hsl(48 90% 90%);
385
+ --sidebar-nav-icon-active-foreground: hsl(48 90% 90%);
386
+ --mega-menu-trigger-current-foreground: hsl(48 90% 90%);
387
+ --mega-menu-trigger-open-foreground: hsl(48 90% 90%);
388
+ --mega-menu-link-current-foreground: hsl(48 90% 90%);
389
+ --timeline-grid-event-muted-color: hsl(0 0% 88%);
390
+
391
+ --focus-ring-color: 0 0% 100%;
392
+ --focus-outline-color: 0 0% 100%;
393
+ --focus-ring-glow-color: 0 0% 100%;
394
+ --control-outline: 0 0% 100%;
395
+ --region-focus-ring-color: hsl(0 0% 100%);
396
+
397
+ --topbar-item-hover-background: 48 90% 22%;
398
+ --topbar-item-hover-color: 0 0% 100%;
399
+ --segmented-item-hover-background: 48 90% 22%;
400
+ --segmented-item-hover-color: 0 0% 100%;
401
+ --segmented-item-active-background: 48 90% 26%;
402
+ --app-launcher-tile-hover-background: 48 90% 22%;
403
+ --app-launcher-tile-hover-color: 0 0% 100%;
404
+ --control-variant-filled-hover-background: 48 90% 22%;
405
+ --choice-button-selected-color: 0 0% 100%;
406
+ --choice-button-selected-border-color: 0 0% 100%;
407
+ --secondary-hover: 48 80% 22%;
408
+ --secondary-active: 48 80% 26%;
409
+
410
+ --menu-item-hover-background: hsl(48 90% 26%);
411
+ --menu-item-hover-foreground: hsl(0 0% 100%);
412
+ --table-row-hover-background: hsl(48 90% 22%);
413
+ --table-row-selected-background: hsl(48 90% 26%);
414
+ --tree-node-hover-background: hsl(48 90% 22%);
415
+ --tree-node-selected-background: hsl(48 90% 26%);
416
+ --tree-node-selected-foreground: hsl(0 0% 100%);
417
+ --mega-menu-trigger-hover-background: hsl(48 90% 26%);
418
+ --mega-menu-trigger-hover-foreground: hsl(0 0% 100%);
419
+ --mega-menu-link-hover-background: hsl(48 90% 26%);
420
+ --mega-menu-link-hover-foreground: hsl(0 0% 100%);
421
+ --sidebar-nav-item-hover-foreground: hsl(0 0% 100%);
422
+ --sidebar-nav-icon-hover-foreground: hsl(0 0% 100%);
423
+ --conversations-item-active-background: hsl(48 90% 26%);
424
+ --conversations-item-active-color: hsl(0 0% 100%);
425
+ --tabs-count-active-background: hsl(48 90% 26%);
426
+ --tabs-count-active-color: hsl(0 0% 100%);
427
+ --toggle-soft-hover-background: hsl(48 90% 24%);
428
+ --toggle-pressed-count-background: hsl(48 90% 26%);
429
+ --toggle-pressed-count-color: hsl(0 0% 100%);
430
+ --toggle-pressed-border-color: hsl(0 0% 100%);
431
+ --switch-unchecked-background: hsl(0 0% 40%);
432
+ --switch-content-unchecked-foreground: hsl(0 0% 96%);
433
+
434
+ --text-action-color: hsl(0 0% 100%);
435
+ --text-action-color-hover: hsl(0 0% 88%);
436
+ }
437
+
438
+ @supports (color: hsl(from red h s l)) {
439
+ .dark [data-theme-style="neubrutalism"],
440
+ [data-theme="dark"] [data-theme-style="neubrutalism"] {
441
+ --muted: from hsl(var(--primary)) h 60% 16%;
442
+ --accent: from hsl(var(--primary)) h 90% 20%;
443
+ --secondary: from hsl(var(--primary)) h 80% 18%;
444
+
445
+ --text-link: from hsl(var(--primary)) h 90% 86%;
446
+ --text-brand: from hsl(var(--primary)) h 90% 86%;
447
+ --text-primary: from hsl(var(--primary)) h 90% 90%;
448
+ --anchor-ink-color: from hsl(var(--primary)) h 90% 86%;
449
+ --sidebar-item-active-foreground: hsl(from hsl(var(--primary)) h 90% 90%);
450
+ --sidebar-nav-icon-active-foreground: hsl(from hsl(var(--primary)) h 90% 90%);
451
+ --mega-menu-trigger-current-foreground: hsl(from hsl(var(--primary)) h 90% 90%);
452
+ --mega-menu-trigger-open-foreground: hsl(from hsl(var(--primary)) h 90% 90%);
453
+ --mega-menu-link-current-foreground: hsl(from hsl(var(--primary)) h 90% 90%);
454
+
455
+ --topbar-item-hover-background: from hsl(var(--primary)) h 90% 22%;
456
+ --segmented-item-hover-background: from hsl(var(--primary)) h 90% 22%;
457
+ --segmented-item-active-background: from hsl(var(--primary)) h 90% 26%;
458
+ --app-launcher-tile-hover-background: from hsl(var(--primary)) h 90% 22%;
459
+ --control-variant-filled-hover-background: from hsl(var(--primary)) h 90% 22%;
460
+ --secondary-hover: from hsl(var(--primary)) h 80% 22%;
461
+ --secondary-active: from hsl(var(--primary)) h 80% 26%;
462
+
463
+ --menu-item-hover-background: hsl(from hsl(var(--primary)) h 90% 26%);
464
+ --table-row-hover-background: hsl(from hsl(var(--primary)) h 90% 22%);
465
+ --table-row-selected-background: hsl(from hsl(var(--primary)) h 90% 26%);
466
+ --tree-node-hover-background: hsl(from hsl(var(--primary)) h 90% 22%);
467
+ --tree-node-selected-background: hsl(from hsl(var(--primary)) h 90% 26%);
468
+ --mega-menu-trigger-hover-background: hsl(from hsl(var(--primary)) h 90% 26%);
469
+ --mega-menu-link-hover-background: hsl(from hsl(var(--primary)) h 90% 26%);
470
+ --conversations-item-active-background: hsl(from hsl(var(--primary)) h 90% 26%);
471
+ --tabs-count-active-background: hsl(from hsl(var(--primary)) h 90% 26%);
472
+ --toggle-soft-hover-background: hsl(from hsl(var(--primary)) h 90% 24%);
473
+ --toggle-pressed-count-background: hsl(from hsl(var(--primary)) h 90% 26%);
474
+ }
475
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@godxjp/ui",
3
- "version": "28.13.0",
4
- "godxUiMcp": "28.13.0",
3
+ "version": "30.0.0",
4
+ "godxUiMcp": "30.0.0",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
7
7
  "type": "git",
@@ -38,6 +38,7 @@
38
38
  "scripts/postinstall.mjs",
39
39
  "scripts/_agent-setup.mjs",
40
40
  "scripts/cli.mjs",
41
+ "scripts/explain-token.mjs",
41
42
  "docs"
42
43
  ],
43
44
  "main": "./dist/index.js",
@@ -392,7 +393,7 @@
392
393
  "lint:fix": "eslint . --fix",
393
394
  "postinstall": "node scripts/postinstall.mjs",
394
395
  "prepublishOnly": "pnpm run build",
395
- "preview": "node preview/scripts/kill-port.mjs && vite --config preview/vite.config.ts --port 6008 --strictPort",
396
+ "preview": "PORT=$(node preview/scripts/preview-port.mjs) && node preview/scripts/kill-port.mjs $PORT && echo \"preview: http://localhost:$PORT\" && vite --config preview/vite.config.ts --port $PORT --strictPort",
396
397
  "preview:build": "vite build --config preview/vite.config.ts && node scripts/gen-registry.mjs && node scripts/copy-agent-catalog.mjs",
397
398
  "regen": "node scripts/regen-generated.mjs",
398
399
  "release": "node scripts/release.mjs",