@kungal/ui-tokens 2.55.0 → 2.56.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,70 @@
1
1
  # @kungal/ui-tokens
2
2
 
3
+ ## 2.56.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 26ffcad: Secondary text now clears WCAG AA on the fills it sits on, not only on the bare page.
8
+
9
+ - **`foreground-muted` is slightly stronger.** It was the ramp's `default-600` in light and `default-500` in dark. That cleared AA on `background` and `content1`, but not on the neutral fills muted text also sits on: a hovered or keyboard-highlighted row (`bg-default/20`), a keycap (`bg-default-100`) and a code-block header (`bg-default/15`). On those it measured as low as 3.95:1 in light and 3.93:1 in dark, and a KunKbd keycap in dark mode read 4.36:1. It is now a grey of its own between the ramp steps: OKLCH L 0.48 in light and 0.66 in dark. That is the smallest move that clears 4.5:1 on all of those fills. On the page it is now 5.98:1 in light and 6.35:1 in dark, up from 5.03:1 and 5.42:1. The token generator now measures it on `background`, on `content1`, on `default/20` over each and on `default-100`, and fails the build if any is below AA. Placeholders use this token, so placeholders on tinted inputs get the same fix. `{c}-text` is now also measured on its own `100` step, the fill of the viewer's own chat bubble; every hue already cleared it.
10
+ - **Text on a tint laid over another tinted surface uses `text-default-text`,** as a flat default chip's label does. This covers KunChatMessageList's unread divider, a `default/15` band on the `default-100` chat wallpaper (4.10:1 in light), and KunChatText's code-block language label inside a coloured bubble (4.12:1 in dark).
11
+ - **No transparency on a fill's on-colour.** White on `primary` is 4.59:1, so any alpha drops it below AA.
12
+ - KunChatConversationItem's selected row drew its time at 80% and its preview at 85%, which measured 3.50:1 and 3.76:1.
13
+ - KunInfo's solid and shadow descriptions were drawn at 90% (4.02:1).
14
+ - Both are now at full strength.
15
+ - **KunChatConversationItem muted-chat badge.** The unread badge of a muted chat was white on `default-400`, 2.53:1 in light. It is now the solid default fill with its own on-colour, 4.87:1.
16
+ - **KunChatBubble.**
17
+ - A deleted reply's "message deleted" line was `default-500` (3.20:1 in light); it is now `foreground-muted`.
18
+ - The time shown over a photo now sits on `bg-black/55` instead of `/45`. White on black/45 over a white screenshot is 3.35:1, and /55 is the lowest opacity that clears 4.5:1 over any image.
19
+
20
+ **What it costs:** muted text renders slightly darker in light mode and slightly lighter in dark mode everywhere it is used. Your code needs no changes. In `tokens.dtcg.json`, `foreground-muted` is now a colour value instead of an alias to a ramp step. In Flutter, `KunColorScheme.foregroundMuted` takes the new value; its API is unchanged.
21
+
22
+ Measured in Chromium on every demo across the 77 component pages, in both modes. The only text still below AA is:
23
+
24
+ - disabled controls;
25
+ - KunLoading's outlined caption, and the content dimmed under its mask;
26
+ - a reaction colour the consumer chose;
27
+ - text on an image or a gradient.
28
+
29
+ ## 2.56.0
30
+
31
+ ### Minor Changes
32
+
33
+ - 570067b: Coloured text and placeholders now clear WCAG AA (4.5:1). A kungal Flutter app's contrast check measured KunUI's own coloured text and placeholders below it, and the web uses the same classes.
34
+
35
+ **New tokens:**
36
+
37
+ - `--color-{color}-text` (Tailwind `text-primary-text`, `text-danger-text`, …), one per semantic colour, `default` included.
38
+ - In Dart: `KunColorScale.text`.
39
+
40
+ **Why a new token.** A fill colour used as text measured 1.75–4.42:1 on the light page for every colour but `default`, and in dark mode primary and danger fell to 3.87:1 and 3.66:1 on cards. `{color}-text` is the ramp step closest to the fill that clears 4.5:1 on:
41
+
42
+ - the page background;
43
+ - cards (`content1`);
44
+ - the colour's own 20% tint over each, which is the hover and keyboard-focus fill of a light item and the fill of a flat chip.
45
+
46
+ The token generator measures all four in both modes and fails the build if one misses. The steps it picks:
47
+
48
+ | Mode | Step 600 | Step 700 |
49
+ | ----- | ----------------------------- | --------------------------------------- |
50
+ | Light | secondary, warning | primary, success, danger, info, default |
51
+ | Dark | every colour except secondary | secondary |
52
+
53
+ **What moved to it:**
54
+
55
+ - The `light`, `bordered` and `flat` variants (buttons, chips, badges, menu items) and `kunTextClasses`, which covers KunLink, selected tabs, active steps and reactions.
56
+ - KunInfo's `bordered` text, and its dark `flat` danger and info.
57
+ - Every form error message and required asterisk.
58
+ - Chat sender names, reply and pinned titles, links, mentions, typing and status text.
59
+
60
+ **What you'll see.** Coloured text is one step darker in light mode and one step lighter in dark mode. Icons, SVG strokes, spinners and text on solid fills keep their colours.
61
+
62
+ **If your own markup uses `text-primary` for readable text**, switch it to `text-primary-text`. `text-primary` stays the fill colour, meant for fills, borders and icons.
63
+
64
+ **Placeholders** now use `foreground-muted`, the secondary-text colour: 5.52:1 light and 4.85:1 dark, where `default-400` measured 2.31–3.58:1. This covers the base-layer `::placeholder` rule (every native input), KunSelect's and KunDatePicker's empty trigger, KunChatComposer and KunCommandPalette. A placeholder is often the only label a field has, such as "全部平台" in a filter. Disabled text, outside-month days and icons keep their lighter steps: WCAG exempts disabled controls, and the others are not text.
65
+
66
+ Measured on the docs site in Chromium: 227 text elements in each mode across the button, chip, tab, link, select, input, info, dropdown, chat bubble, date picker and textarea pages all clear 4.5:1. The lowest are a warning chip (4.77:1 light, 4.87:1 dark) and the dark placeholder (4.85:1).
67
+
3
68
  ## 2.55.0
4
69
 
5
70
  ## 2.54.0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kungal/ui-tokens",
3
- "version": "2.55.0",
3
+ "version": "2.56.1",
4
4
  "description": "KunUI design tokens — framework-agnostic Tailwind v4 theme (semantic colors, radius, z-index, animations).",
5
5
  "type": "module",
6
6
  "keywords": [
package/src/base.css CHANGED
@@ -81,11 +81,14 @@
81
81
  min-height: 100vh;
82
82
  }
83
83
 
84
- /* Placeholder text — a muted neutral that flips with the theme (the browser
85
- * default is a fixed grey that doesn't follow light/dark). `opacity: 1` since
86
- * the colour already carries its own muting and UA sheets dim placeholders. */
84
+ /* Placeholder text — the secondary-text colour, which flips with the theme
85
+ * (the browser default is a fixed grey that doesn't follow light/dark).
86
+ * default-400 measured 2.31:1 on the light page and 3.21:1 on dark cards;
87
+ * foreground-muted is held at 4.5:1 by the token generator. A placeholder
88
+ * often carries the only label a field has ("全部平台"). `opacity: 1` since
89
+ * UA sheets dim placeholders. */
87
90
  ::placeholder {
88
- color: oklch(var(--default-400));
91
+ color: oklch(var(--foreground-muted));
89
92
  opacity: 1;
90
93
  }
91
94
  }
@@ -19,6 +19,7 @@
19
19
 
20
20
  --color-primary: oklch(var(--primary-accent));
21
21
  --color-primary-foreground: oklch(var(--primary-on));
22
+ --color-primary-text: oklch(var(--primary-text));
22
23
  --color-primary-50: oklch(var(--primary-50));
23
24
  --color-primary-100: oklch(var(--primary-100));
24
25
  --color-primary-200: oklch(var(--primary-200));
@@ -33,6 +34,7 @@
33
34
 
34
35
  --color-secondary: oklch(var(--secondary-accent));
35
36
  --color-secondary-foreground: oklch(var(--secondary-on));
37
+ --color-secondary-text: oklch(var(--secondary-text));
36
38
  --color-secondary-50: oklch(var(--secondary-50));
37
39
  --color-secondary-100: oklch(var(--secondary-100));
38
40
  --color-secondary-200: oklch(var(--secondary-200));
@@ -47,6 +49,7 @@
47
49
 
48
50
  --color-success: oklch(var(--success-accent));
49
51
  --color-success-foreground: oklch(var(--success-on));
52
+ --color-success-text: oklch(var(--success-text));
50
53
  --color-success-50: oklch(var(--success-50));
51
54
  --color-success-100: oklch(var(--success-100));
52
55
  --color-success-200: oklch(var(--success-200));
@@ -61,6 +64,7 @@
61
64
 
62
65
  --color-warning: oklch(var(--warning-accent));
63
66
  --color-warning-foreground: oklch(var(--warning-on));
67
+ --color-warning-text: oklch(var(--warning-text));
64
68
  --color-warning-50: oklch(var(--warning-50));
65
69
  --color-warning-100: oklch(var(--warning-100));
66
70
  --color-warning-200: oklch(var(--warning-200));
@@ -75,6 +79,7 @@
75
79
 
76
80
  --color-danger: oklch(var(--danger-accent));
77
81
  --color-danger-foreground: oklch(var(--danger-on));
82
+ --color-danger-text: oklch(var(--danger-text));
78
83
  --color-danger-50: oklch(var(--danger-50));
79
84
  --color-danger-100: oklch(var(--danger-100));
80
85
  --color-danger-200: oklch(var(--danger-200));
@@ -89,6 +94,7 @@
89
94
 
90
95
  --color-info: oklch(var(--info-accent));
91
96
  --color-info-foreground: oklch(var(--info-on));
97
+ --color-info-text: oklch(var(--info-text));
92
98
  --color-info-50: oklch(var(--info-50));
93
99
  --color-info-100: oklch(var(--info-100));
94
100
  --color-info-200: oklch(var(--info-200));
@@ -103,6 +109,7 @@
103
109
 
104
110
  --color-default: oklch(var(--default-accent));
105
111
  --color-default-foreground: oklch(var(--default-on));
112
+ --color-default-text: oklch(var(--default-text));
106
113
  --color-default-50: oklch(var(--default-50));
107
114
  --color-default-100: oklch(var(--default-100) / var(--kun-global-opacity));
108
115
  --color-default-200: oklch(var(--default-200));
@@ -120,7 +127,7 @@
120
127
  :root {
121
128
  --background: 0.968 0.004 286.33;
122
129
  --foreground: 0.2057 0.0132 233.66;
123
- --foreground-muted: 0.52 0.015 285.9;
130
+ --foreground-muted: 0.48 0.015 285.9;
124
131
  --content1: 1 0 0;
125
132
  --content2: 0.9683 0.0014 286.37;
126
133
  --content3: 0.9197 0.0041 286.32;
@@ -129,6 +136,7 @@
129
136
  /* Blue */
130
137
  --primary-accent: 0.57 0.2 257.9;
131
138
  --primary-on: 1 0 0;
139
+ --primary-text: 0.44 0.1622 257.9;
132
140
  --primary-50: 0.972 0.0133 257.9;
133
141
  --primary-100: 0.945 0.0264 257.9;
134
142
  --primary-200: 0.892 0.0528 257.9;
@@ -144,6 +152,7 @@
144
152
  /* Magenta */
145
153
  --secondary-accent: 0.8 0.1524 341.5;
146
154
  --secondary-on: 0.2 0.03 341.5;
155
+ --secondary-text: 0.52 0.2244 341.5;
147
156
  --secondary-50: 0.972 0.018 341.5;
148
157
  --secondary-100: 0.945 0.0362 341.5;
149
158
  --secondary-200: 0.892 0.0748 341.5;
@@ -159,6 +168,7 @@
159
168
  /* Green */
160
169
  --success-accent: 0.72 0.18 150.9;
161
170
  --success-on: 0.2 0.03 150.9;
171
+ --success-text: 0.44 0.1186 150.9;
162
172
  --success-50: 0.972 0.0446 150.9;
163
173
  --success-100: 0.945 0.0914 150.9;
164
174
  --success-200: 0.892 0.18 150.9;
@@ -174,6 +184,7 @@
174
184
  /* Amber */
175
185
  --warning-accent: 0.8 0.1686 72.2;
176
186
  --warning-on: 0.2 0.03 72.2;
187
+ --warning-text: 0.52 0.1112 72.2;
177
188
  --warning-50: 0.972 0.0211 72.2;
178
189
  --warning-100: 0.945 0.0421 72.2;
179
190
  --warning-200: 0.892 0.0855 72.2;
@@ -189,6 +200,7 @@
189
200
  /* Red */
190
201
  --danger-accent: 0.58 0.23 11.1;
191
202
  --danger-on: 1 0 0;
203
+ --danger-text: 0.44 0.1759 11.1;
192
204
  --danger-50: 0.972 0.0139 11.1;
193
205
  --danger-100: 0.945 0.028 11.1;
194
206
  --danger-200: 0.892 0.0577 11.1;
@@ -204,6 +216,7 @@
204
216
  /* Cyan */
205
217
  --info-accent: 0.7 0.1262 218.5;
206
218
  --info-on: 0.2 0.03 218.5;
219
+ --info-text: 0.44 0.0793 218.5;
207
220
  --info-50: 0.972 0.0201 218.5;
208
221
  --info-100: 0.945 0.0398 218.5;
209
222
  --info-200: 0.892 0.0796 218.5;
@@ -219,6 +232,7 @@
219
232
  /* Neutral */
220
233
  --default-accent: 0.55 0.015 285.9;
221
234
  --default-on: 1 0 0;
235
+ --default-text: 0.44 0.015 285.9;
222
236
  --default-50: 0.972 0.0137 285.9;
223
237
  --default-100: 0.945 0.015 285.9;
224
238
  --default-200: 0.892 0.015 285.9;
@@ -235,7 +249,7 @@
235
249
  .kun-dark-mode {
236
250
  --background: 0.1448 0 0;
237
251
  --foreground: 0.946 0.0018 247.84;
238
- --foreground-muted: 0.62 0.015 285.9;
252
+ --foreground-muted: 0.66 0.015 285.9;
239
253
  --content1: 0.2102 0.006 285.87;
240
254
  --content2: 0.2747 0.006 286;
241
255
  --content3: 0.3701 0.0113 285.84;
@@ -244,6 +258,7 @@
244
258
  /* Blue */
245
259
  --primary-accent: 0.57 0.2 257.9;
246
260
  --primary-on: 1 0 0;
261
+ --primary-text: 0.715 0.1495 257.9;
247
262
  --primary-50: 0.215 0.0792 257.9;
248
263
  --primary-100: 0.28 0.1032 257.9;
249
264
  --primary-200: 0.36 0.1327 257.9;
@@ -259,6 +274,7 @@
259
274
  /* Magenta */
260
275
  --secondary-accent: 0.8 0.1524 341.5;
261
276
  --secondary-on: 0.2 0.03 341.5;
277
+ --secondary-text: 0.82 0.1342 341.5;
262
278
  --secondary-50: 0.215 0.0928 341.5;
263
279
  --secondary-100: 0.28 0.1208 341.5;
264
280
  --secondary-200: 0.36 0.1554 341.5;
@@ -274,6 +290,7 @@
274
290
  /* Green */
275
291
  --success-accent: 0.72 0.18 150.9;
276
292
  --success-on: 0.2 0.03 150.9;
293
+ --success-text: 0.715 0.18 150.9;
277
294
  --success-50: 0.215 0.058 150.9;
278
295
  --success-100: 0.28 0.0755 150.9;
279
296
  --success-200: 0.36 0.0971 150.9;
@@ -289,6 +306,7 @@
289
306
  /* Amber */
290
307
  --warning-accent: 0.8 0.1686 72.2;
291
308
  --warning-on: 0.2 0.03 72.2;
309
+ --warning-text: 0.715 0.1529 72.2;
292
310
  --warning-50: 0.215 0.046 72.2;
293
311
  --warning-100: 0.28 0.0599 72.2;
294
312
  --warning-200: 0.36 0.077 72.2;
@@ -304,6 +322,7 @@
304
322
  /* Red */
305
323
  --danger-accent: 0.58 0.23 11.1;
306
324
  --danger-on: 1 0 0;
325
+ --danger-text: 0.715 0.1833 11.1;
307
326
  --danger-50: 0.215 0.0859 11.1;
308
327
  --danger-100: 0.28 0.1119 11.1;
309
328
  --danger-200: 0.36 0.1439 11.1;
@@ -319,6 +338,7 @@
319
338
  /* Cyan */
320
339
  --info-accent: 0.7 0.1262 218.5;
321
340
  --info-on: 0.2 0.03 218.5;
341
+ --info-text: 0.715 0.1289 218.5;
322
342
  --info-50: 0.215 0.0387 218.5;
323
343
  --info-100: 0.28 0.0505 218.5;
324
344
  --info-200: 0.36 0.0649 218.5;
@@ -334,6 +354,7 @@
334
354
  /* Neutral */
335
355
  --default-accent: 0.55 0.015 285.9;
336
356
  --default-on: 1 0 0;
357
+ --default-text: 0.715 0.015 285.9;
337
358
  --default-50: 0.215 0.015 285.9;
338
359
  --default-100: 0.28 0.015 285.9;
339
360
  --default-200: 0.36 0.015 285.9;
@@ -197,6 +197,10 @@
197
197
  "alpha": 1,
198
198
  "hex": "#ffffff"
199
199
  }
200
+ },
201
+ "text": {
202
+ "$type": "color",
203
+ "$value": "{color.light.primary.700}"
200
204
  }
201
205
  },
202
206
  "secondary": {
@@ -368,6 +372,10 @@
368
372
  "alpha": 1,
369
373
  "hex": "#1f101a"
370
374
  }
375
+ },
376
+ "text": {
377
+ "$type": "color",
378
+ "$value": "{color.light.secondary.600}"
371
379
  }
372
380
  },
373
381
  "success": {
@@ -539,6 +547,10 @@
539
547
  "alpha": 1,
540
548
  "hex": "#0b1a0f"
541
549
  }
550
+ },
551
+ "text": {
552
+ "$type": "color",
553
+ "$value": "{color.light.success.700}"
542
554
  }
543
555
  },
544
556
  "warning": {
@@ -710,6 +722,10 @@
710
722
  "alpha": 1,
711
723
  "hex": "#1e1406"
712
724
  }
725
+ },
726
+ "text": {
727
+ "$type": "color",
728
+ "$value": "{color.light.warning.600}"
713
729
  }
714
730
  },
715
731
  "danger": {
@@ -881,6 +897,10 @@
881
897
  "alpha": 1,
882
898
  "hex": "#ffffff"
883
899
  }
900
+ },
901
+ "text": {
902
+ "$type": "color",
903
+ "$value": "{color.light.danger.700}"
884
904
  }
885
905
  },
886
906
  "info": {
@@ -1052,6 +1072,10 @@
1052
1072
  "alpha": 1,
1053
1073
  "hex": "#04191f"
1054
1074
  }
1075
+ },
1076
+ "text": {
1077
+ "$type": "color",
1078
+ "$value": "{color.light.info.700}"
1055
1079
  }
1056
1080
  },
1057
1081
  "default": {
@@ -1223,6 +1247,10 @@
1223
1247
  "alpha": 1,
1224
1248
  "hex": "#ffffff"
1225
1249
  }
1250
+ },
1251
+ "text": {
1252
+ "$type": "color",
1253
+ "$value": "{color.light.default.700}"
1226
1254
  }
1227
1255
  },
1228
1256
  "background": {
@@ -1309,7 +1337,16 @@
1309
1337
  },
1310
1338
  "foreground-muted": {
1311
1339
  "$type": "color",
1312
- "$value": "{color.light.default.600}"
1340
+ "$value": {
1341
+ "colorSpace": "oklch",
1342
+ "components": [
1343
+ 0.48,
1344
+ 0.015,
1345
+ 285.9
1346
+ ],
1347
+ "alpha": 1,
1348
+ "hex": "#5d5d66"
1349
+ }
1313
1350
  }
1314
1351
  },
1315
1352
  "dark": {
@@ -1482,6 +1519,10 @@
1482
1519
  "alpha": 1,
1483
1520
  "hex": "#ffffff"
1484
1521
  }
1522
+ },
1523
+ "text": {
1524
+ "$type": "color",
1525
+ "$value": "{color.dark.primary.600}"
1485
1526
  }
1486
1527
  },
1487
1528
  "secondary": {
@@ -1653,6 +1694,10 @@
1653
1694
  "alpha": 1,
1654
1695
  "hex": "#1f101a"
1655
1696
  }
1697
+ },
1698
+ "text": {
1699
+ "$type": "color",
1700
+ "$value": "{color.dark.secondary.700}"
1656
1701
  }
1657
1702
  },
1658
1703
  "success": {
@@ -1824,6 +1869,10 @@
1824
1869
  "alpha": 1,
1825
1870
  "hex": "#0b1a0f"
1826
1871
  }
1872
+ },
1873
+ "text": {
1874
+ "$type": "color",
1875
+ "$value": "{color.dark.success.600}"
1827
1876
  }
1828
1877
  },
1829
1878
  "warning": {
@@ -1995,6 +2044,10 @@
1995
2044
  "alpha": 1,
1996
2045
  "hex": "#1e1406"
1997
2046
  }
2047
+ },
2048
+ "text": {
2049
+ "$type": "color",
2050
+ "$value": "{color.dark.warning.600}"
1998
2051
  }
1999
2052
  },
2000
2053
  "danger": {
@@ -2166,6 +2219,10 @@
2166
2219
  "alpha": 1,
2167
2220
  "hex": "#ffffff"
2168
2221
  }
2222
+ },
2223
+ "text": {
2224
+ "$type": "color",
2225
+ "$value": "{color.dark.danger.600}"
2169
2226
  }
2170
2227
  },
2171
2228
  "info": {
@@ -2337,6 +2394,10 @@
2337
2394
  "alpha": 1,
2338
2395
  "hex": "#04191f"
2339
2396
  }
2397
+ },
2398
+ "text": {
2399
+ "$type": "color",
2400
+ "$value": "{color.dark.info.600}"
2340
2401
  }
2341
2402
  },
2342
2403
  "default": {
@@ -2508,6 +2569,10 @@
2508
2569
  "alpha": 1,
2509
2570
  "hex": "#ffffff"
2510
2571
  }
2572
+ },
2573
+ "text": {
2574
+ "$type": "color",
2575
+ "$value": "{color.dark.default.600}"
2511
2576
  }
2512
2577
  },
2513
2578
  "background": {
@@ -2594,7 +2659,16 @@
2594
2659
  },
2595
2660
  "foreground-muted": {
2596
2661
  "$type": "color",
2597
- "$value": "{color.dark.default.500}"
2662
+ "$value": {
2663
+ "colorSpace": "oklch",
2664
+ "components": [
2665
+ 0.66,
2666
+ 0.015,
2667
+ 285.9
2668
+ ],
2669
+ "alpha": 1,
2670
+ "hex": "#91919b"
2671
+ }
2598
2672
  }
2599
2673
  }
2600
2674
  },