@godxjp/ui 25.4.0 → 26.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.
- package/dist/app/theme-axes.js +7 -5
- package/dist/contracts/measurement.json +1 -1
- package/dist/styles/base.css +6 -2
- package/dist/styles/control.css +1 -1
- package/dist/styles/focus-ring.css +23 -2
- package/dist/styles/shell-layout.css +2 -2
- package/dist/styles/text-layout.css +5 -2
- package/dist/tokens/axes.css +2 -2
- package/dist/tokens/components/text.css +3 -2
- package/dist/tokens/derived.css +38 -12
- package/dist/tokens/foundation.css +3 -3
- package/docs/CUSTOMER-THEMING.md +37 -1
- package/docs/DESIGN-AUTHORITY.md +8 -4
- package/package.json +2 -2
package/dist/app/theme-axes.js
CHANGED
|
@@ -60,14 +60,16 @@ function applyPrimaryColor(root, color, foreground) {
|
|
|
60
60
|
const hue = delta === 0 ? 0 : 60 * (max === r ? ((g - b) / delta + 6) % 6 : max === g ? (b - r) / delta + 2 : (r - g) / delta + 4);
|
|
61
61
|
return `${hue} ${saturation * 100}% ${lightness * 100}%`;
|
|
62
62
|
};
|
|
63
|
-
const
|
|
64
|
-
const shade = (amount) => hsl(rgb.map((channel) => channel * (1 - amount) + away * amount));
|
|
63
|
+
const polarity = luminance(text) > 0.5 ? "darken" : "lighten";
|
|
65
64
|
const palette = {
|
|
66
65
|
"--primary": hsl(rgb),
|
|
67
66
|
"--primary-foreground": hsl(text),
|
|
68
|
-
"--primary-hover":
|
|
69
|
-
"--primary-active":
|
|
70
|
-
"--primary-border":
|
|
67
|
+
"--primary-hover": "initial",
|
|
68
|
+
"--primary-active": "initial",
|
|
69
|
+
"--primary-border": "initial",
|
|
70
|
+
"--control-outline": "initial",
|
|
71
|
+
"--primary-hover-channels": `var(--primary-hover-${polarity}-channels)`,
|
|
72
|
+
"--primary-active-channels": `var(--primary-active-${polarity}-channels)`,
|
|
71
73
|
"--ring": hsl(rgb)
|
|
72
74
|
};
|
|
73
75
|
const previous = Object.keys(palette).map((key) => [
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$comment": "AUTO-GENERATED by scripts/gen-measurement-contract.mjs — do not edit. Read this instead of guessing: docs/MEASUREMENT-CONTRACT.md.",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "26.0.0",
|
|
4
4
|
"targetSize": {
|
|
5
5
|
"standard": "WCAG 2.2 SC 2.5.8 Target Size (Minimum), level AA — 24×24 CSS px",
|
|
6
6
|
"min": 24,
|
package/dist/styles/base.css
CHANGED
|
@@ -100,8 +100,12 @@
|
|
|
100
100
|
--color-link: hsl(var(--text-link));
|
|
101
101
|
--color-brand: hsl(var(--text-brand));
|
|
102
102
|
|
|
103
|
-
--color-primary-hover: hsl(
|
|
104
|
-
|
|
103
|
+
--color-primary-hover: hsl(
|
|
104
|
+
var(--primary-hover, from hsl(var(--primary)) var(--primary-hover-channels))
|
|
105
|
+
);
|
|
106
|
+
--color-primary-active: hsl(
|
|
107
|
+
var(--primary-active, from hsl(var(--primary)) var(--primary-active-channels))
|
|
108
|
+
);
|
|
105
109
|
--color-secondary-hover: hsl(var(--secondary-hover));
|
|
106
110
|
--color-secondary-active: hsl(var(--secondary-active));
|
|
107
111
|
--color-destructive-hover: hsl(var(--destructive-hover));
|
package/dist/styles/control.css
CHANGED
|
@@ -114,8 +114,29 @@
|
|
|
114
114
|
:root[data-focus-outline="on"] .ui-otp-slot[data-active="true"],
|
|
115
115
|
:root[data-focus-outline="on"]
|
|
116
116
|
.ui-otp-group[data-appearance="grouped"]:has(.ui-otp-slot[data-active="true"]) {
|
|
117
|
-
|
|
118
|
-
|
|
117
|
+
|
|
118
|
+
--tw-ring-shadow: var(
|
|
119
|
+
--focus-field-shadow,
|
|
120
|
+
0 0 0 var(--focus-ring-glow-width)
|
|
121
|
+
hsl(
|
|
122
|
+
var(
|
|
123
|
+
--focus-ring-glow-color,
|
|
124
|
+
var(--control-outline, from hsl(var(--primary)) var(--control-outline-channels))
|
|
125
|
+
) /
|
|
126
|
+
var(--focus-ring-glow-alpha)
|
|
127
|
+
)
|
|
128
|
+
);
|
|
129
|
+
box-shadow: var(
|
|
130
|
+
--focus-field-shadow,
|
|
131
|
+
0 0 0 var(--focus-ring-glow-width)
|
|
132
|
+
hsl(
|
|
133
|
+
var(
|
|
134
|
+
--focus-ring-glow-color,
|
|
135
|
+
var(--control-outline, from hsl(var(--primary)) var(--control-outline-channels))
|
|
136
|
+
) /
|
|
137
|
+
var(--focus-ring-glow-alpha)
|
|
138
|
+
)
|
|
139
|
+
);
|
|
119
140
|
}
|
|
120
141
|
|
|
121
142
|
:root[data-focus-outline="on"]
|
|
@@ -1651,7 +1651,7 @@
|
|
|
1651
1651
|
transparent
|
|
1652
1652
|
)
|
|
1653
1653
|
);
|
|
1654
|
-
color: var(--sidebar-item-active-foreground, hsl(var(--primary)));
|
|
1654
|
+
color: var(--sidebar-item-active-foreground, hsl(var(--primary-active, from hsl(var(--primary)) var(--primary-active-channels))));
|
|
1655
1655
|
font-weight: var(--font-weight-medium);
|
|
1656
1656
|
}
|
|
1657
1657
|
|
|
@@ -1768,7 +1768,7 @@
|
|
|
1768
1768
|
|
|
1769
1769
|
.sb-nav-item--sub[data-active="true"] {
|
|
1770
1770
|
background: transparent;
|
|
1771
|
-
color: var(--sidebar-item-active-foreground, hsl(var(--primary)));
|
|
1771
|
+
color: var(--sidebar-item-active-foreground, hsl(var(--primary-active, from hsl(var(--primary)) var(--primary-active-channels))));
|
|
1772
1772
|
font-weight: var(--font-weight-medium);
|
|
1773
1773
|
}
|
|
1774
1774
|
|
|
@@ -231,7 +231,7 @@
|
|
|
231
231
|
border: 0;
|
|
232
232
|
background: none;
|
|
233
233
|
padding: 0;
|
|
234
|
-
color: var(--text-action-color);
|
|
234
|
+
color: var(--text-action-color, hsl(var(--primary)));
|
|
235
235
|
font: inherit;
|
|
236
236
|
cursor: pointer;
|
|
237
237
|
vertical-align: baseline;
|
|
@@ -242,7 +242,10 @@
|
|
|
242
242
|
}
|
|
243
243
|
.ui-typography-action:hover,
|
|
244
244
|
.ui-typography-action:focus-visible {
|
|
245
|
-
color: var(
|
|
245
|
+
color: var(
|
|
246
|
+
--text-action-color-hover,
|
|
247
|
+
hsl(var(--primary-hover, from hsl(var(--primary)) var(--primary-hover-channels)))
|
|
248
|
+
);
|
|
246
249
|
}
|
|
247
250
|
|
|
248
251
|
.ui-typography-action[data-copied] {
|
package/dist/tokens/axes.css
CHANGED
|
@@ -63,8 +63,8 @@
|
|
|
63
63
|
|
|
64
64
|
:root[data-focus-outline="on"] {
|
|
65
65
|
--focus-outline: 1;
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
|
|
67
|
+
--focus-field-shadow: initial;
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
:root[data-focus-outline="off"] {
|
|
@@ -12,8 +12,9 @@
|
|
|
12
12
|
|
|
13
13
|
--text-action-gap: var(--space-1);
|
|
14
14
|
|
|
15
|
-
--text-action-color:
|
|
16
|
-
|
|
15
|
+
--text-action-color: initial;
|
|
16
|
+
|
|
17
|
+
--text-action-color-hover: initial;
|
|
17
18
|
|
|
18
19
|
--text-action-size: 1em;
|
|
19
20
|
|
package/dist/tokens/derived.css
CHANGED
|
@@ -2,17 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
:root {
|
|
4
4
|
|
|
5
|
-
--primary-hover:
|
|
5
|
+
--primary-hover: initial;
|
|
6
|
+
--primary-active: initial;
|
|
7
|
+
--primary-border: initial;
|
|
8
|
+
--control-outline: initial;
|
|
6
9
|
|
|
7
|
-
--primary-
|
|
10
|
+
--primary-hover-darken-channels: h s calc(l - 8.4);
|
|
11
|
+
--primary-active-darken-channels: h s calc(l - 15.5);
|
|
12
|
+
--primary-hover-lighten-channels: h s calc(l + 5.8);
|
|
13
|
+
--primary-active-lighten-channels: h s calc(l + 11.6 - 17.4 * clamp(0, (l - 83.4) * 1000, 1));
|
|
8
14
|
|
|
9
|
-
--primary-
|
|
10
|
-
--
|
|
11
|
-
|
|
15
|
+
--primary-hover-channels: var(--primary-hover-darken-channels);
|
|
16
|
+
--primary-active-channels: var(--primary-active-darken-channels);
|
|
17
|
+
|
|
18
|
+
--primary-border-channels: h calc(s * 0.68) calc(l + 16);
|
|
12
19
|
|
|
13
|
-
--control-outline:
|
|
20
|
+
--control-outline-channels: h s calc(l - 5.3);
|
|
14
21
|
--control-outline-alpha: 0.11;
|
|
15
22
|
|
|
23
|
+
--destructive-hover: 359 50.6% 53.1%;
|
|
24
|
+
--destructive-active: 355 70.6% 33.3%;
|
|
25
|
+
|
|
16
26
|
--control-outline-error: 4.3 87.6% 34.7%;
|
|
17
27
|
--control-outline-error-alpha: 0.09;
|
|
18
28
|
|
|
@@ -21,20 +31,36 @@
|
|
|
21
31
|
|
|
22
32
|
.dark,
|
|
23
33
|
:root[data-theme="dark"] {
|
|
34
|
+
--primary-hover-channels: var(--primary-hover-lighten-channels);
|
|
35
|
+
--primary-active-channels: var(--primary-active-lighten-channels);
|
|
24
36
|
|
|
25
|
-
--primary-
|
|
37
|
+
--primary-border-channels: h calc(s * 0.467) calc(l * 0.27043);
|
|
26
38
|
|
|
27
|
-
--
|
|
39
|
+
--control-outline-channels: h calc(s * 0.99) calc(l - 25.1);
|
|
40
|
+
--control-outline-alpha: 0.29;
|
|
28
41
|
|
|
29
|
-
--primary-border: 268.7 46.7% 23.5%;
|
|
30
42
|
--destructive-hover: 358.8 42.3% 53.1%;
|
|
31
43
|
--destructive-active: 357.3 50.6% 34.1%;
|
|
32
44
|
|
|
33
|
-
--control-outline: 268.7 99% 61.8%;
|
|
34
|
-
--control-outline-alpha: 0.29;
|
|
35
|
-
|
|
36
45
|
--control-outline-error: 351.5 98.3% 53.5%;
|
|
37
46
|
--control-outline-error-alpha: 0.06;
|
|
38
47
|
|
|
39
48
|
--ring: var(--primary);
|
|
40
49
|
}
|
|
50
|
+
|
|
51
|
+
@supports not (color: hsl(from red h s l)) {
|
|
52
|
+
:root {
|
|
53
|
+
--primary-hover: 268.7 100% 41.6%;
|
|
54
|
+
--primary-active: 268.7 100% 34.5%;
|
|
55
|
+
--primary-border: 268.7 68% 66%;
|
|
56
|
+
--control-outline: 268.7 100% 44.7%;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.dark,
|
|
60
|
+
:root[data-theme="dark"] {
|
|
61
|
+
--primary-hover: 268.7 100% 92.7%;
|
|
62
|
+
--primary-active: 268.7 100% 81.1%;
|
|
63
|
+
--primary-border: 268.7 46.7% 23.5%;
|
|
64
|
+
--control-outline: 268.7 99% 61.8%;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -125,11 +125,11 @@
|
|
|
125
125
|
--focus-ring-opacity: 1;
|
|
126
126
|
|
|
127
127
|
--focus-ring-glow-width: var(--control-outline-width);
|
|
128
|
-
|
|
128
|
+
|
|
129
|
+
--focus-ring-glow-color: initial;
|
|
129
130
|
--focus-ring-glow-alpha: var(--control-outline-alpha);
|
|
130
131
|
|
|
131
|
-
--focus-field-shadow:
|
|
132
|
-
hsl(var(--focus-ring-glow-color) / var(--focus-ring-glow-alpha));
|
|
132
|
+
--focus-field-shadow: initial;
|
|
133
133
|
|
|
134
134
|
--focus-ring-offset: var(--focus-outline-offset);
|
|
135
135
|
|
package/docs/CUSTOMER-THEMING.md
CHANGED
|
@@ -230,7 +230,43 @@ Scope the overrides under a tenant attribute instead of `:root`. The colour util
|
|
|
230
230
|
}
|
|
231
231
|
```
|
|
232
232
|
|
|
233
|
-
Set `data-tenant` on the app root.
|
|
233
|
+
Set `data-tenant` on the app root.
|
|
234
|
+
|
|
235
|
+
#### What follows `--primary`, and what you still set (gh#678)
|
|
236
|
+
|
|
237
|
+
The interaction states are **derived from the `--primary` in scope, at the element that paints them** — on `<html>` or on any nested `[data-tenant]` / `[data-program]` element, in both themes. You do not declare them:
|
|
238
|
+
|
|
239
|
+
| Token | Follows `--primary`? | Default (evaluated at the painting element) |
|
|
240
|
+
| --- | --- | --- |
|
|
241
|
+
| `--primary-hover` | **yes** — Button hover, `bg-primary-hover`, Typography action hover | `hsl(from hsl(var(--primary)) var(--primary-hover-channels))` — light `h s calc(l - 8.4)`, dark `h s calc(l + 5.8)` |
|
|
242
|
+
| `--primary-active` | **yes** — `bg-primary-active`, the open sidebar row's label | light `h s calc(l - 15.5)`; dark one step further up, reflected to one step down past 83.4% L |
|
|
243
|
+
| `--control-outline` | **yes** — the focused field's halo (`--control-outline-alpha` stays per theme) | light `h s calc(l - 5.3)`, dark `h calc(s * 0.99) calc(l - 25.1)` |
|
|
244
|
+
| `--primary-border` | **yes** (painted by no package surface; kept for the measurement in DESIGN-AUTHORITY) | light `h calc(s * 0.68) calc(l + 16)`, dark `h calc(s * 0.467) calc(l * 0.27043)` |
|
|
245
|
+
| `--sidebar-item-active-foreground` | **yes** — defaults to the live `--primary-active` | — |
|
|
246
|
+
| `--primary-foreground` | **no — set it** | the label on a filled primary; you choose it for your seed |
|
|
247
|
+
| `--ring` | **only on the element that declares `--primary`** — set it in a nested scope | `var(--primary)` on `:root` / `.dark`. `--ring` is a public role read as `hsl(var(--ring))` in consumer CSS, so it cannot become a live default; a scope below `<html>` inherits the root's |
|
|
248
|
+
| `--destructive-*`, `--control-outline-error` | no — not brand | literals |
|
|
249
|
+
|
|
250
|
+
On the package seed these produce exactly the identity kit values the tier used to hard-code (`#6500d4` / `#5400b0` light, `#ecdaff` / `#cd9fff` dark). Engines without CSS relative colour (Chrome/Edge 111–118) get those literals and do **not** follow a consumer seed.
|
|
251
|
+
|
|
252
|
+
**Rules that come with it:**
|
|
253
|
+
|
|
254
|
+
- **Override a state only by setting its knob** (`--primary-hover: 221 90% 72%`). A set knob wins over the derived default, in its own scope and below.
|
|
255
|
+
- **Read a state through its fallback, not bare.** The four knobs are `initial` so that the default can resolve at the painting element (docs/TOKENS.md, the freeze rule). `hsl(var(--primary-hover))` on its own therefore paints nothing — use the utility (`bg-primary-hover`) or `hsl(var(--primary-hover, from hsl(var(--primary)) var(--primary-hover-channels)))`.
|
|
256
|
+
- **Label polarity.** The theme's pair steps AWAY from that theme's default label: `darken` under a light label, `lighten` under a dark one, which keeps a label that clears 4.5:1 at rest at 4.5:1 in hover and pressed for every seed (measured, `derived-seed-sweep.test.ts`). If your seed needs the OTHER polarity of label (a pale yellow with dark text in the light theme), point the pair at it too — `applyPrimaryColor()` does this automatically from the label it picks:
|
|
257
|
+
|
|
258
|
+
```css
|
|
259
|
+
[data-tenant="sunny"] {
|
|
260
|
+
--primary: 48 100% 60%;
|
|
261
|
+
--primary-foreground: 48 9% 9%;
|
|
262
|
+
--primary-hover-channels: var(--primary-hover-lighten-channels);
|
|
263
|
+
--primary-active-channels: var(--primary-active-lighten-channels);
|
|
264
|
+
}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
- **The open sidebar row** is legible (≥ 4.5:1 on the 12% tint) for any seed that is itself legible as text on the page. A seed that is not (a pale seed on the light page, a very dark one on the dark page) needs `--sidebar-item-active-foreground` set.
|
|
268
|
+
|
|
269
|
+
Two more CSS-inheritance caveats for the **scoped** case (a single `:root` brand theme is unaffected — there, overriding just `--radius` / `--shadow-color` cascades):
|
|
234
270
|
|
|
235
271
|
- **Radius & shadow-tint don't cascade from a scoped anchor.** `--radius-{xs…2xl}`, `--card-radius`, `--control-radius` and the `--shadow-{xs…2xl}` ramp are computed at their declaring element, so a scoped `--radius` / `--shadow-color` override won't reach them. For a scoped re-theme, re-declare the derived tokens you need (e.g. `--card-radius: var(--radius)`, or set `--card-shadow` to a literal value).
|
|
236
272
|
````
|
package/docs/DESIGN-AUTHORITY.md
CHANGED
|
@@ -437,11 +437,15 @@ anywhere in `src/`, or leaves a trace in `dist/`. Deleting that gate re-opens th
|
|
|
437
437
|
spacer. This library takes a different, two-form convention instead — widely used in enterprise
|
|
438
438
|
component libraries, and surveyed across several before it was adopted here:
|
|
439
439
|
|
|
440
|
-
- **Field** — the boundary RECOLOURS to the primary at its unchanged hairline width, plus
|
|
441
|
-
|
|
440
|
+
- **Field** — the boundary RECOLOURS to the primary at its unchanged hairline width, plus a
|
|
441
|
+
`--control-outline-width` halo in the `--control-outline` colour. A Select emits the same
|
|
442
442
|
declarations as an Input, which is why the two focus identically.
|
|
443
|
-
- **Non-field** — an outline outside the box model
|
|
444
|
-
|
|
443
|
+
- **Non-field** — an outline outside the box model, `--focus-outline-weight` thick in the
|
|
444
|
+
`--primary-border` colour, `outline-offset: 1px`.
|
|
445
|
+
|
|
446
|
+
Since 26.0.0 (gh#678) `--control-outline` and `--primary-border` are `initial` knobs whose default
|
|
447
|
+
derives from `--primary` at the painting element, so a bare `var(--control-outline)` paints
|
|
448
|
+
**nothing**. Read them through their fallback — see `docs/CUSTOMER-THEMING.md` §Multi-tenant.
|
|
445
449
|
|
|
446
450
|
**Why this shape wins.** The library previously shipped an opaque brand ring drawn immediately
|
|
447
451
|
outside an untouched grey border — two outlines of different colours claiming the same edge — and a
|