@hanzo/ui 8.0.51 → 8.0.53

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/glass.css CHANGED
@@ -17,6 +17,18 @@
17
17
  * declaration (an undefined var() invalidates the whole property). They are a
18
18
  * mirror, not a second opinion — glass.test.ts reads @hanzo/design/styles.css
19
19
  * and fails if any of them stops matching, so the copy cannot drift.
20
+ *
21
+ * Reached BY ROLE, never by size. A role name (--edge-highlight,
22
+ * --surface-scrim) is coined for one job and only design declares it. The
23
+ * t-shirt ramp — --shadow-sm/md/lg/xl — is the opposite: a generic scale that
24
+ * every token package ships, and @hanzo/brand ships one too, at :root, tuned
25
+ * for a WHITE canvas (.05/.1 against design's .40/.55). Same names, same
26
+ * specificity, so the winner is whichever sheet the bundler ordered last, and
27
+ * it was brand. A declared variable also beats a var() fallback outright — so
28
+ * the mirror above could not save the rungs that read a ramp name, and on
29
+ * #080808 their drops resolved to a shadow you cannot see. The lit edge kept
30
+ * the ladder from vanishing, which is why it read as flat rather than as
31
+ * broken. The ladder therefore declares its own drops below; see there.
20
32
  */
21
33
 
22
34
  /* ── The material ───────────────────────────────────────────────────────────
@@ -77,11 +89,47 @@
77
89
 
78
90
  Glass over glass (a select opened inside a dialog) is deliberately left to
79
91
  stack: two 72% grounds land near 92%, so the nested surface reads as MORE
80
- solid than its parent, which is the right answer and the one macOS gives. */
92
+ solid than its parent, which is the right answer and the one macOS gives.
93
+
94
+ ── The rungs' drops are this package's own, and that is the fix ────────────
95
+ A rung used to read the ramp by size — var(--shadow-sm | --shadow-lg) — and
96
+ a name you do not own is a value somebody else gets to set. @hanzo/brand
97
+ sets exactly those, at :root, for a white canvas, and won on load order.
98
+ Three values are three names, so they are declared here: nothing else ships
99
+ a --glass-shadow-*, so no sheet can outrank them and no load order can
100
+ change the answer. A theme that wants a different ladder declares these
101
+ three and gets one; that is a hook, where reading the ramp was an accident.
102
+
103
+ Only the DROP is owned. --edge-highlight stays design's, because it is
104
+ role-named, uncollided, and design's `.light` zeroing of it is the half of
105
+ the composition that makes one rule work on both canvases.
106
+
107
+ Both themes are stated for the same reason design states them: on white the
108
+ drop does all the work and must be light enough not to smudge, on near-black
109
+ it must be heavy enough to exist at all. The values are design's own, and
110
+ glass.test.ts fails if either column stops matching what design publishes.
111
+ `:root.t_light` and `.t_light` alongside `.light` are gui's spelling of the
112
+ same idea — compose-theme teaches design's sheet those aliases, and this
113
+ file, which also ships on its own, says them outright. The bare class is for
114
+ a NESTED light scope: gui puts `t_light` on a span for `<Theme name="light">`
115
+ inside a dark app, which `:root.t_light` cannot match, so without it a light
116
+ island stood on the dark ladder. */
117
+ :root {
118
+ --glass-shadow-1: 0 1px 2px 0 rgb(0 0 0 / .40);
119
+ --glass-shadow-2: 0 10px 15px -3px rgb(0 0 0 / .55), 0 4px 6px -4px rgb(0 0 0 / .55);
120
+ --glass-shadow-3: 0 24px 60px -16px rgb(0 0 0 / .75);
121
+ }
122
+
123
+ .light, :root.t_light, .t_light {
124
+ --glass-shadow-1: 0 1px 2px 0 rgb(0 0 0 / .06);
125
+ --glass-shadow-2: 0 10px 15px -3px rgb(0 0 0 / .09), 0 4px 6px -4px rgb(0 0 0 / .07);
126
+ --glass-shadow-3: 0 24px 60px -16px rgb(0 0 0 / .18);
127
+ }
128
+
81
129
  .elevation-1 {
82
130
  box-shadow:
83
131
  var(--edge-highlight, inset 0 1px 0 0 rgb(255 255 255 / .10)),
84
- var(--shadow-sm, 0 1px 2px 0 rgb(0 0 0 / .40)) !important;
132
+ var(--glass-shadow-1) !important;
85
133
  }
86
134
 
87
135
  .elevation-2,
@@ -92,14 +140,14 @@
92
140
  [data-slot="tooltip-content"] {
93
141
  box-shadow:
94
142
  var(--edge-highlight, inset 0 1px 0 0 rgb(255 255 255 / .10)),
95
- var(--shadow-lg, 0 10px 15px -3px rgb(0 0 0 / .55), 0 4px 6px -4px rgb(0 0 0 / .55)) !important;
143
+ var(--glass-shadow-2) !important;
96
144
  }
97
145
 
98
146
  .elevation-3,
99
147
  [data-slot="dialog-content"] {
100
148
  box-shadow:
101
149
  var(--edge-highlight, inset 0 1px 0 0 rgb(255 255 255 / .10)),
102
- var(--shadow-floating, 0 24px 60px -16px rgb(0 0 0 / .75)) !important;
150
+ var(--glass-shadow-3) !important;
103
151
  }
104
152
 
105
153
  /* ── The scrim ──────────────────────────────────────────────────────────────
@@ -111,10 +159,19 @@
111
159
 
112
160
  One value, in one place: the recipes module reads the same token, so the dim
113
161
  behind a component dialog and the dim behind a hand-rolled one are the same
114
- dim by construction rather than by two people remembering a number. */
162
+ dim by construction rather than by two people remembering a number.
163
+
164
+ !important for the same reason the material above carries it, and it was
165
+ missing here: gui compiles `opacity` and `background-color` into atomic
166
+ classes (`_o-0--5`, `_bg-rgba0000--538295333`) that land in an inline <style>
167
+ a bundler orders AFTER this sheet, so at equal specificity they won and the
168
+ rule read as if it had never been written. Measured on hanzo.app's ⌘K
169
+ palette: `rgba(0,0,0,.5)` under `opacity: .5` — a quarter black, exactly the
170
+ double dim these two lines exist to end. A rule written to beat a compiled
171
+ class has to be written with the weight to beat one. */
115
172
  [data-slot="dialog-overlay"] {
116
- opacity: 1;
117
- background-color: var(--surface-scrim, rgb(0 0 0 / .8));
173
+ opacity: 1 !important;
174
+ background-color: var(--surface-scrim, rgb(0 0 0 / .8)) !important;
118
175
  }
119
176
 
120
177
  /* ── Grouped rows ───────────────────────────────────────────────────────────
@@ -141,8 +141,55 @@ for (const [k, v] of Object.entries(STEP)) {
141
141
  }
142
142
  space.$true = STEP['4'];
143
143
  space['-true'] = -STEP['4'];
144
+ /**
145
+ * TWO RUNGS OF THE NUMBERED RAMP UNDID A TOKEN DECISION, so they are re-based.
146
+ *
147
+ * `$color1..$color12` is a generic monotonic ramp inherited from upstream
148
+ * `@hanzogui/themes` — a scale, not this system's token layer. Most of it is
149
+ * harmless: a ramp of greys is a ramp of greys. Two rungs are not, because
150
+ * every component in this package reads them by name and @hanzo/design had
151
+ * already decided each one the other way, in writing:
152
+ *
153
+ * `$borderColor` (= `$color4`) shipped `hsla(0, 0%, 14%, 1)` — a SOLID edge.
154
+ * design's `colors.css` spends a paragraph on why its borders are alpha: a
155
+ * solid hex hairline vanishes the moment it lands on a lifted surface,
156
+ * because it stops being a lighter line and becomes an unrelated grey. Nearly
157
+ * every component here (Button, Input, Card, Select, Dialog, Popover,
158
+ * Tooltip, Switch, Checkbox, DropdownMenu) draws its edge with it.
159
+ *
160
+ * `$color12` shipped `hsla(0, 0%, 100%, 1)` — PURE WHITE, and it is the label
161
+ * colour for Button's default/primary, for every Badge, and for the `accent`
162
+ * recipe, the one loud control a page is allowed. design sets `--foreground`
163
+ * to `#fafafa` on purpose: pure white halates on near-black.
164
+ *
165
+ * So the two rungs read the token instead of shadowing it. `var()` first, so a
166
+ * host that mounts design's sheet (this package's own theme.css does) follows
167
+ * the live cascade and inverts with it; design's published literal behind it,
168
+ * so a host that mounts neither still gets the right value rather than a
169
+ * dropped declaration.
170
+ *
171
+ * The literals are stated per theme rather than left to the cascade, and that
172
+ * is load-bearing: a NESTED `<Theme name="light">` (PrimaryButton's white pill
173
+ * inside a dark app) emits `.t_light` on a span, not on `:root`, so the light
174
+ * column has to be able to answer on its own. gui-config.test.ts reads
175
+ * @hanzo/design's stylesheet and fails if either column stops matching what
176
+ * design publishes, so the copy cannot drift.
177
+ */
178
+ const EDGE = { dark: 'rgb(255 255 255 / .10)', light: 'rgb(0 0 0 / .10)' };
179
+ const LABEL = { dark: '#fafafa', light: '#0a0a0a' };
180
+ const rebased = (theme) => ({
181
+ ...v5_1.defaultConfig.themes[theme],
182
+ color4: `var(--border, ${EDGE[theme]})`,
183
+ borderColor: `var(--border, ${EDGE[theme]})`,
184
+ color12: `var(--foreground, ${LABEL[theme]})`,
185
+ });
144
186
  exports.config = (0, gui_1.createGui)({
145
187
  ...v5_1.defaultConfig,
188
+ themes: {
189
+ ...v5_1.defaultConfig.themes,
190
+ dark: rebased('dark'),
191
+ light: rebased('light'),
192
+ },
146
193
  tokens: {
147
194
  ...v5_1.defaultConfig.tokens,
148
195
  radius: RADIUS,