@timmo001/groundwork-tokens 0.5.0 → 0.7.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/generated/themes.css +75 -16
- package/generated/themes.json +14 -0
- package/generated/themes.ts +14 -0
- package/package.json +3 -2
- package/src/generate.ts +66 -37
- package/src/index.ts +2 -0
- package/src/page.ts +14 -3
- package/src/runtime.ts +18 -0
- package/src/tones.ts +87 -0
package/generated/themes.css
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
:root {
|
|
4
4
|
--gw-density: 1;
|
|
5
|
+
--gw-control-scale: 1;
|
|
5
6
|
--gw-space-0-5: calc(0.125rem * var(--gw-density));
|
|
6
7
|
--gw-space-1: calc(0.25rem * var(--gw-density));
|
|
7
8
|
--gw-space-2: calc(0.5rem * var(--gw-density));
|
|
@@ -67,7 +68,7 @@ gw-button:not(:defined),
|
|
|
67
68
|
gw-menu-button:not(:defined),
|
|
68
69
|
gw-segmented:not(:defined) {
|
|
69
70
|
display: inline-block;
|
|
70
|
-
min-block-size: 2.5rem;
|
|
71
|
+
min-block-size: calc(2.5rem * var(--gw-control-scale, 1));
|
|
71
72
|
vertical-align: middle;
|
|
72
73
|
}
|
|
73
74
|
|
|
@@ -75,30 +76,46 @@ gw-button:not(:defined) {
|
|
|
75
76
|
padding-inline: calc(var(--gw-space-4) + 1px);
|
|
76
77
|
font-size: var(--gw-font-size-s);
|
|
77
78
|
font-weight: var(--gw-font-weight-strong);
|
|
78
|
-
line-height: 2.5rem;
|
|
79
|
+
line-height: calc(2.5rem * var(--gw-control-scale, 1));
|
|
79
80
|
white-space: nowrap;
|
|
80
81
|
text-transform: var(--gw-label-transform);
|
|
81
82
|
letter-spacing: var(--gw-label-tracking);
|
|
82
83
|
}
|
|
83
84
|
|
|
84
85
|
gw-button[size="xs"]:not(:defined) {
|
|
85
|
-
min-block-size: 1.5rem;
|
|
86
|
-
line-height: 1.5rem;
|
|
86
|
+
min-block-size: calc(1.5rem * var(--gw-control-scale, 1));
|
|
87
|
+
line-height: calc(1.5rem * var(--gw-control-scale, 1));
|
|
87
88
|
}
|
|
88
89
|
|
|
89
90
|
gw-button[size="small"]:not(:defined) {
|
|
90
|
-
min-block-size: 2rem;
|
|
91
|
-
line-height: 2rem;
|
|
91
|
+
min-block-size: calc(2rem * var(--gw-control-scale, 1));
|
|
92
|
+
line-height: calc(2rem * var(--gw-control-scale, 1));
|
|
92
93
|
}
|
|
93
94
|
|
|
94
95
|
gw-button[size="large"]:not(:defined) {
|
|
95
|
-
min-block-size: 3rem;
|
|
96
|
-
line-height: 3rem;
|
|
96
|
+
min-block-size: calc(3rem * var(--gw-control-scale, 1));
|
|
97
|
+
line-height: calc(3rem * var(--gw-control-scale, 1));
|
|
97
98
|
}
|
|
98
99
|
|
|
99
100
|
gw-button[size="xl"]:not(:defined) {
|
|
100
|
-
min-block-size: 3.5rem;
|
|
101
|
-
line-height: 3.5rem;
|
|
101
|
+
min-block-size: calc(3.5rem * var(--gw-control-scale, 1));
|
|
102
|
+
line-height: calc(3.5rem * var(--gw-control-scale, 1));
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
gw-menu-button[size="xs"]:not(:defined) {
|
|
106
|
+
min-block-size: calc(1.5rem * var(--gw-control-scale, 1));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
gw-menu-button[size="small"]:not(:defined) {
|
|
110
|
+
min-block-size: calc(2rem * var(--gw-control-scale, 1));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
gw-menu-button[size="large"]:not(:defined) {
|
|
114
|
+
min-block-size: calc(3rem * var(--gw-control-scale, 1));
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
gw-menu-button[size="xl"]:not(:defined) {
|
|
118
|
+
min-block-size: calc(3.5rem * var(--gw-control-scale, 1));
|
|
102
119
|
}
|
|
103
120
|
|
|
104
121
|
gw-card:not(:defined) {
|
|
@@ -168,16 +185,44 @@ gw-button:not(:defined) > [slot="icon"] {
|
|
|
168
185
|
|
|
169
186
|
gw-chip:not(:defined) {
|
|
170
187
|
display: inline-flex;
|
|
171
|
-
min-block-size: 2rem;
|
|
188
|
+
min-block-size: calc(2rem * var(--gw-control-scale, 1));
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
gw-chip[size="xs"]:not(:defined) {
|
|
192
|
+
min-block-size: calc(1.2rem * var(--gw-control-scale, 1));
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
gw-chip[size="small"]:not(:defined) {
|
|
196
|
+
min-block-size: calc(1.6rem * var(--gw-control-scale, 1));
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
gw-chip[size="large"]:not(:defined) {
|
|
200
|
+
min-block-size: calc(2.4rem * var(--gw-control-scale, 1));
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
gw-chip[size="xl"]:not(:defined) {
|
|
204
|
+
min-block-size: calc(2.8rem * var(--gw-control-scale, 1));
|
|
172
205
|
}
|
|
173
206
|
|
|
174
207
|
gw-badge:not(:defined) {
|
|
175
208
|
display: inline-flex;
|
|
176
|
-
min-block-size: 2.25rem;
|
|
209
|
+
min-block-size: calc(2.25rem * var(--gw-control-scale, 1));
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
gw-badge[size="xs"]:not(:defined) {
|
|
213
|
+
min-block-size: calc(1.35rem * var(--gw-control-scale, 1));
|
|
177
214
|
}
|
|
178
215
|
|
|
179
216
|
gw-badge[size="small"]:not(:defined) {
|
|
180
|
-
min-block-size: 1.
|
|
217
|
+
min-block-size: calc(1.8rem * var(--gw-control-scale, 1));
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
gw-badge[size="large"]:not(:defined) {
|
|
221
|
+
min-block-size: calc(2.7rem * var(--gw-control-scale, 1));
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
gw-badge[size="xl"]:not(:defined) {
|
|
225
|
+
min-block-size: calc(3.15rem * var(--gw-control-scale, 1));
|
|
181
226
|
}
|
|
182
227
|
|
|
183
228
|
gw-dot:not(:defined) {
|
|
@@ -211,19 +256,19 @@ gw-skeleton-icon:not(:defined) {
|
|
|
211
256
|
gw-input:not(:defined),
|
|
212
257
|
gw-select:not(:defined) {
|
|
213
258
|
display: flex;
|
|
214
|
-
min-block-size:
|
|
259
|
+
min-block-size: calc(2rem + calc(2.5rem * var(--gw-control-scale, 1)));
|
|
215
260
|
}
|
|
216
261
|
|
|
217
262
|
gw-input:is([hint]:not(:defined),
|
|
218
263
|
[error]):not(:defined),
|
|
219
264
|
gw-select:is([hint]:not(:defined),
|
|
220
265
|
[error]):not(:defined) {
|
|
221
|
-
min-block-size:
|
|
266
|
+
min-block-size: calc(3.75rem + calc(2.5rem * var(--gw-control-scale, 1)));
|
|
222
267
|
}
|
|
223
268
|
|
|
224
269
|
gw-select:is([label-hidden]:not(:defined),
|
|
225
270
|
[inline-label]):not(:defined) {
|
|
226
|
-
min-block-size: 2.5rem;
|
|
271
|
+
min-block-size: calc(2.5rem * var(--gw-control-scale, 1));
|
|
227
272
|
}
|
|
228
273
|
|
|
229
274
|
gw-select[inline-label]:not(:defined) {
|
|
@@ -270,6 +315,7 @@ gw-option-list:not(:defined) {
|
|
|
270
315
|
--gw-font-weight-regular: 400;
|
|
271
316
|
--gw-font-weight-strong: 600;
|
|
272
317
|
--gw-density: 1;
|
|
318
|
+
--gw-control-scale: 1;
|
|
273
319
|
--gw-space-0-5: calc(0.125rem * var(--gw-density));
|
|
274
320
|
--gw-space-1: calc(0.25rem * var(--gw-density));
|
|
275
321
|
--gw-space-2: calc(0.5rem * var(--gw-density));
|
|
@@ -524,6 +570,7 @@ gw-option-list:not(:defined) {
|
|
|
524
570
|
--gw-font-weight-regular: 400;
|
|
525
571
|
--gw-font-weight-strong: 600;
|
|
526
572
|
--gw-density: 1.2;
|
|
573
|
+
--gw-control-scale: 1.1;
|
|
527
574
|
--gw-space-0-5: calc(0.125rem * var(--gw-density));
|
|
528
575
|
--gw-space-1: calc(0.25rem * var(--gw-density));
|
|
529
576
|
--gw-space-2: calc(0.5rem * var(--gw-density));
|
|
@@ -778,6 +825,7 @@ gw-option-list:not(:defined) {
|
|
|
778
825
|
--gw-font-weight-regular: 500;
|
|
779
826
|
--gw-font-weight-strong: 700;
|
|
780
827
|
--gw-density: 1;
|
|
828
|
+
--gw-control-scale: 1;
|
|
781
829
|
--gw-space-0-5: calc(0.125rem * var(--gw-density));
|
|
782
830
|
--gw-space-1: calc(0.25rem * var(--gw-density));
|
|
783
831
|
--gw-space-2: calc(0.5rem * var(--gw-density));
|
|
@@ -1032,6 +1080,7 @@ gw-option-list:not(:defined) {
|
|
|
1032
1080
|
--gw-font-weight-regular: 400;
|
|
1033
1081
|
--gw-font-weight-strong: 600;
|
|
1034
1082
|
--gw-density: 1;
|
|
1083
|
+
--gw-control-scale: 1;
|
|
1035
1084
|
--gw-space-0-5: calc(0.125rem * var(--gw-density));
|
|
1036
1085
|
--gw-space-1: calc(0.25rem * var(--gw-density));
|
|
1037
1086
|
--gw-space-2: calc(0.5rem * var(--gw-density));
|
|
@@ -1286,6 +1335,7 @@ gw-option-list:not(:defined) {
|
|
|
1286
1335
|
--gw-font-weight-regular: 400;
|
|
1287
1336
|
--gw-font-weight-strong: 600;
|
|
1288
1337
|
--gw-density: 1;
|
|
1338
|
+
--gw-control-scale: 1;
|
|
1289
1339
|
--gw-space-0-5: calc(0.125rem * var(--gw-density));
|
|
1290
1340
|
--gw-space-1: calc(0.25rem * var(--gw-density));
|
|
1291
1341
|
--gw-space-2: calc(0.5rem * var(--gw-density));
|
|
@@ -1540,6 +1590,7 @@ gw-option-list:not(:defined) {
|
|
|
1540
1590
|
--gw-font-weight-regular: 400;
|
|
1541
1591
|
--gw-font-weight-strong: 600;
|
|
1542
1592
|
--gw-density: 0.85;
|
|
1593
|
+
--gw-control-scale: 0.85;
|
|
1543
1594
|
--gw-space-0-5: calc(0.125rem * var(--gw-density));
|
|
1544
1595
|
--gw-space-1: calc(0.25rem * var(--gw-density));
|
|
1545
1596
|
--gw-space-2: calc(0.5rem * var(--gw-density));
|
|
@@ -1794,6 +1845,7 @@ gw-option-list:not(:defined) {
|
|
|
1794
1845
|
--gw-font-weight-regular: 400;
|
|
1795
1846
|
--gw-font-weight-strong: 600;
|
|
1796
1847
|
--gw-density: 1;
|
|
1848
|
+
--gw-control-scale: 1;
|
|
1797
1849
|
--gw-space-0-5: calc(0.125rem * var(--gw-density));
|
|
1798
1850
|
--gw-space-1: calc(0.25rem * var(--gw-density));
|
|
1799
1851
|
--gw-space-2: calc(0.5rem * var(--gw-density));
|
|
@@ -1994,6 +2046,7 @@ gw-option-list:not(:defined) {
|
|
|
1994
2046
|
--gw-font-weight-regular: 400;
|
|
1995
2047
|
--gw-font-weight-strong: 600;
|
|
1996
2048
|
--gw-density: 1;
|
|
2049
|
+
--gw-control-scale: 1;
|
|
1997
2050
|
--gw-space-0-5: calc(0.125rem * var(--gw-density));
|
|
1998
2051
|
--gw-space-1: calc(0.25rem * var(--gw-density));
|
|
1999
2052
|
--gw-space-2: calc(0.5rem * var(--gw-density));
|
|
@@ -2090,6 +2143,7 @@ gw-option-list:not(:defined) {
|
|
|
2090
2143
|
--gw-font-weight-regular: 400;
|
|
2091
2144
|
--gw-font-weight-strong: 600;
|
|
2092
2145
|
--gw-density: 1;
|
|
2146
|
+
--gw-control-scale: 1;
|
|
2093
2147
|
--gw-space-0-5: calc(0.125rem * var(--gw-density));
|
|
2094
2148
|
--gw-space-1: calc(0.25rem * var(--gw-density));
|
|
2095
2149
|
--gw-space-2: calc(0.5rem * var(--gw-density));
|
|
@@ -2290,6 +2344,7 @@ gw-option-list:not(:defined) {
|
|
|
2290
2344
|
--gw-font-weight-regular: 400;
|
|
2291
2345
|
--gw-font-weight-strong: 600;
|
|
2292
2346
|
--gw-density: 1;
|
|
2347
|
+
--gw-control-scale: 1;
|
|
2293
2348
|
--gw-space-0-5: calc(0.125rem * var(--gw-density));
|
|
2294
2349
|
--gw-space-1: calc(0.25rem * var(--gw-density));
|
|
2295
2350
|
--gw-space-2: calc(0.5rem * var(--gw-density));
|
|
@@ -2490,6 +2545,7 @@ gw-option-list:not(:defined) {
|
|
|
2490
2545
|
--gw-font-weight-regular: 400;
|
|
2491
2546
|
--gw-font-weight-strong: 600;
|
|
2492
2547
|
--gw-density: 1;
|
|
2548
|
+
--gw-control-scale: 1;
|
|
2493
2549
|
--gw-space-0-5: calc(0.125rem * var(--gw-density));
|
|
2494
2550
|
--gw-space-1: calc(0.25rem * var(--gw-density));
|
|
2495
2551
|
--gw-space-2: calc(0.5rem * var(--gw-density));
|
|
@@ -2690,6 +2746,7 @@ gw-option-list:not(:defined) {
|
|
|
2690
2746
|
--gw-font-weight-regular: 400;
|
|
2691
2747
|
--gw-font-weight-strong: 600;
|
|
2692
2748
|
--gw-density: 1;
|
|
2749
|
+
--gw-control-scale: 1;
|
|
2693
2750
|
--gw-space-0-5: calc(0.125rem * var(--gw-density));
|
|
2694
2751
|
--gw-space-1: calc(0.25rem * var(--gw-density));
|
|
2695
2752
|
--gw-space-2: calc(0.5rem * var(--gw-density));
|
|
@@ -2786,6 +2843,7 @@ gw-option-list:not(:defined) {
|
|
|
2786
2843
|
--gw-font-weight-regular: 400;
|
|
2787
2844
|
--gw-font-weight-strong: 600;
|
|
2788
2845
|
--gw-density: 1;
|
|
2846
|
+
--gw-control-scale: 1;
|
|
2789
2847
|
--gw-space-0-5: calc(0.125rem * var(--gw-density));
|
|
2790
2848
|
--gw-space-1: calc(0.25rem * var(--gw-density));
|
|
2791
2849
|
--gw-space-2: calc(0.5rem * var(--gw-density));
|
|
@@ -2986,6 +3044,7 @@ gw-option-list:not(:defined) {
|
|
|
2986
3044
|
--gw-font-weight-regular: 400;
|
|
2987
3045
|
--gw-font-weight-strong: 600;
|
|
2988
3046
|
--gw-density: 1;
|
|
3047
|
+
--gw-control-scale: 1;
|
|
2989
3048
|
--gw-space-0-5: calc(0.125rem * var(--gw-density));
|
|
2990
3049
|
--gw-space-1: calc(0.25rem * var(--gw-density));
|
|
2991
3050
|
--gw-space-2: calc(0.5rem * var(--gw-density));
|
package/generated/themes.json
CHANGED
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
"font-weight-regular": "400",
|
|
40
40
|
"font-weight-strong": "600",
|
|
41
41
|
"density": "1",
|
|
42
|
+
"control-scale": "1",
|
|
42
43
|
"space-0-5": "calc(0.125rem * var(--gw-density))",
|
|
43
44
|
"space-1": "calc(0.25rem * var(--gw-density))",
|
|
44
45
|
"space-2": "calc(0.5rem * var(--gw-density))",
|
|
@@ -258,6 +259,7 @@
|
|
|
258
259
|
"font-weight-regular": "400",
|
|
259
260
|
"font-weight-strong": "600",
|
|
260
261
|
"density": "1.2",
|
|
262
|
+
"control-scale": "1.1",
|
|
261
263
|
"space-0-5": "calc(0.125rem * var(--gw-density))",
|
|
262
264
|
"space-1": "calc(0.25rem * var(--gw-density))",
|
|
263
265
|
"space-2": "calc(0.5rem * var(--gw-density))",
|
|
@@ -477,6 +479,7 @@
|
|
|
477
479
|
"font-weight-regular": "500",
|
|
478
480
|
"font-weight-strong": "700",
|
|
479
481
|
"density": "1",
|
|
482
|
+
"control-scale": "1",
|
|
480
483
|
"space-0-5": "calc(0.125rem * var(--gw-density))",
|
|
481
484
|
"space-1": "calc(0.25rem * var(--gw-density))",
|
|
482
485
|
"space-2": "calc(0.5rem * var(--gw-density))",
|
|
@@ -696,6 +699,7 @@
|
|
|
696
699
|
"font-weight-regular": "400",
|
|
697
700
|
"font-weight-strong": "600",
|
|
698
701
|
"density": "1",
|
|
702
|
+
"control-scale": "1",
|
|
699
703
|
"space-0-5": "calc(0.125rem * var(--gw-density))",
|
|
700
704
|
"space-1": "calc(0.25rem * var(--gw-density))",
|
|
701
705
|
"space-2": "calc(0.5rem * var(--gw-density))",
|
|
@@ -917,6 +921,7 @@
|
|
|
917
921
|
"font-weight-regular": "400",
|
|
918
922
|
"font-weight-strong": "600",
|
|
919
923
|
"density": "1",
|
|
924
|
+
"control-scale": "1",
|
|
920
925
|
"space-0-5": "calc(0.125rem * var(--gw-density))",
|
|
921
926
|
"space-1": "calc(0.25rem * var(--gw-density))",
|
|
922
927
|
"space-2": "calc(0.5rem * var(--gw-density))",
|
|
@@ -1138,6 +1143,7 @@
|
|
|
1138
1143
|
"font-weight-regular": "400",
|
|
1139
1144
|
"font-weight-strong": "600",
|
|
1140
1145
|
"density": "0.85",
|
|
1146
|
+
"control-scale": "0.85",
|
|
1141
1147
|
"space-0-5": "calc(0.125rem * var(--gw-density))",
|
|
1142
1148
|
"space-1": "calc(0.25rem * var(--gw-density))",
|
|
1143
1149
|
"space-2": "calc(0.5rem * var(--gw-density))",
|
|
@@ -1357,6 +1363,7 @@
|
|
|
1357
1363
|
"font-weight-regular": "400",
|
|
1358
1364
|
"font-weight-strong": "600",
|
|
1359
1365
|
"density": "1",
|
|
1366
|
+
"control-scale": "1",
|
|
1360
1367
|
"space-0-5": "calc(0.125rem * var(--gw-density))",
|
|
1361
1368
|
"space-1": "calc(0.25rem * var(--gw-density))",
|
|
1362
1369
|
"space-2": "calc(0.5rem * var(--gw-density))",
|
|
@@ -1529,6 +1536,7 @@
|
|
|
1529
1536
|
"font-weight-regular": "400",
|
|
1530
1537
|
"font-weight-strong": "600",
|
|
1531
1538
|
"density": "1",
|
|
1539
|
+
"control-scale": "1",
|
|
1532
1540
|
"space-0-5": "calc(0.125rem * var(--gw-density))",
|
|
1533
1541
|
"space-1": "calc(0.25rem * var(--gw-density))",
|
|
1534
1542
|
"space-2": "calc(0.5rem * var(--gw-density))",
|
|
@@ -1654,6 +1662,7 @@
|
|
|
1654
1662
|
"font-weight-regular": "400",
|
|
1655
1663
|
"font-weight-strong": "600",
|
|
1656
1664
|
"density": "1",
|
|
1665
|
+
"control-scale": "1",
|
|
1657
1666
|
"space-0-5": "calc(0.125rem * var(--gw-density))",
|
|
1658
1667
|
"space-1": "calc(0.25rem * var(--gw-density))",
|
|
1659
1668
|
"space-2": "calc(0.5rem * var(--gw-density))",
|
|
@@ -1826,6 +1835,7 @@
|
|
|
1826
1835
|
"font-weight-regular": "400",
|
|
1827
1836
|
"font-weight-strong": "600",
|
|
1828
1837
|
"density": "1",
|
|
1838
|
+
"control-scale": "1",
|
|
1829
1839
|
"space-0-5": "calc(0.125rem * var(--gw-density))",
|
|
1830
1840
|
"space-1": "calc(0.25rem * var(--gw-density))",
|
|
1831
1841
|
"space-2": "calc(0.5rem * var(--gw-density))",
|
|
@@ -1998,6 +2008,7 @@
|
|
|
1998
2008
|
"font-weight-regular": "400",
|
|
1999
2009
|
"font-weight-strong": "600",
|
|
2000
2010
|
"density": "1",
|
|
2011
|
+
"control-scale": "1",
|
|
2001
2012
|
"space-0-5": "calc(0.125rem * var(--gw-density))",
|
|
2002
2013
|
"space-1": "calc(0.25rem * var(--gw-density))",
|
|
2003
2014
|
"space-2": "calc(0.5rem * var(--gw-density))",
|
|
@@ -2170,6 +2181,7 @@
|
|
|
2170
2181
|
"font-weight-regular": "400",
|
|
2171
2182
|
"font-weight-strong": "600",
|
|
2172
2183
|
"density": "1",
|
|
2184
|
+
"control-scale": "1",
|
|
2173
2185
|
"space-0-5": "calc(0.125rem * var(--gw-density))",
|
|
2174
2186
|
"space-1": "calc(0.25rem * var(--gw-density))",
|
|
2175
2187
|
"space-2": "calc(0.5rem * var(--gw-density))",
|
|
@@ -2295,6 +2307,7 @@
|
|
|
2295
2307
|
"font-weight-regular": "400",
|
|
2296
2308
|
"font-weight-strong": "600",
|
|
2297
2309
|
"density": "1",
|
|
2310
|
+
"control-scale": "1",
|
|
2298
2311
|
"space-0-5": "calc(0.125rem * var(--gw-density))",
|
|
2299
2312
|
"space-1": "calc(0.25rem * var(--gw-density))",
|
|
2300
2313
|
"space-2": "calc(0.5rem * var(--gw-density))",
|
|
@@ -2467,6 +2480,7 @@
|
|
|
2467
2480
|
"font-weight-regular": "400",
|
|
2468
2481
|
"font-weight-strong": "600",
|
|
2469
2482
|
"density": "1",
|
|
2483
|
+
"control-scale": "1",
|
|
2470
2484
|
"space-0-5": "calc(0.125rem * var(--gw-density))",
|
|
2471
2485
|
"space-1": "calc(0.25rem * var(--gw-density))",
|
|
2472
2486
|
"space-2": "calc(0.5rem * var(--gw-density))",
|
package/generated/themes.ts
CHANGED
|
@@ -40,6 +40,7 @@ export const themes = [
|
|
|
40
40
|
"font-weight-regular": "400",
|
|
41
41
|
"font-weight-strong": "600",
|
|
42
42
|
"density": "1",
|
|
43
|
+
"control-scale": "1",
|
|
43
44
|
"space-0-5": "calc(0.125rem * var(--gw-density))",
|
|
44
45
|
"space-1": "calc(0.25rem * var(--gw-density))",
|
|
45
46
|
"space-2": "calc(0.5rem * var(--gw-density))",
|
|
@@ -259,6 +260,7 @@ export const themes = [
|
|
|
259
260
|
"font-weight-regular": "400",
|
|
260
261
|
"font-weight-strong": "600",
|
|
261
262
|
"density": "1.2",
|
|
263
|
+
"control-scale": "1.1",
|
|
262
264
|
"space-0-5": "calc(0.125rem * var(--gw-density))",
|
|
263
265
|
"space-1": "calc(0.25rem * var(--gw-density))",
|
|
264
266
|
"space-2": "calc(0.5rem * var(--gw-density))",
|
|
@@ -478,6 +480,7 @@ export const themes = [
|
|
|
478
480
|
"font-weight-regular": "500",
|
|
479
481
|
"font-weight-strong": "700",
|
|
480
482
|
"density": "1",
|
|
483
|
+
"control-scale": "1",
|
|
481
484
|
"space-0-5": "calc(0.125rem * var(--gw-density))",
|
|
482
485
|
"space-1": "calc(0.25rem * var(--gw-density))",
|
|
483
486
|
"space-2": "calc(0.5rem * var(--gw-density))",
|
|
@@ -697,6 +700,7 @@ export const themes = [
|
|
|
697
700
|
"font-weight-regular": "400",
|
|
698
701
|
"font-weight-strong": "600",
|
|
699
702
|
"density": "1",
|
|
703
|
+
"control-scale": "1",
|
|
700
704
|
"space-0-5": "calc(0.125rem * var(--gw-density))",
|
|
701
705
|
"space-1": "calc(0.25rem * var(--gw-density))",
|
|
702
706
|
"space-2": "calc(0.5rem * var(--gw-density))",
|
|
@@ -918,6 +922,7 @@ export const themes = [
|
|
|
918
922
|
"font-weight-regular": "400",
|
|
919
923
|
"font-weight-strong": "600",
|
|
920
924
|
"density": "1",
|
|
925
|
+
"control-scale": "1",
|
|
921
926
|
"space-0-5": "calc(0.125rem * var(--gw-density))",
|
|
922
927
|
"space-1": "calc(0.25rem * var(--gw-density))",
|
|
923
928
|
"space-2": "calc(0.5rem * var(--gw-density))",
|
|
@@ -1139,6 +1144,7 @@ export const themes = [
|
|
|
1139
1144
|
"font-weight-regular": "400",
|
|
1140
1145
|
"font-weight-strong": "600",
|
|
1141
1146
|
"density": "0.85",
|
|
1147
|
+
"control-scale": "0.85",
|
|
1142
1148
|
"space-0-5": "calc(0.125rem * var(--gw-density))",
|
|
1143
1149
|
"space-1": "calc(0.25rem * var(--gw-density))",
|
|
1144
1150
|
"space-2": "calc(0.5rem * var(--gw-density))",
|
|
@@ -1358,6 +1364,7 @@ export const themes = [
|
|
|
1358
1364
|
"font-weight-regular": "400",
|
|
1359
1365
|
"font-weight-strong": "600",
|
|
1360
1366
|
"density": "1",
|
|
1367
|
+
"control-scale": "1",
|
|
1361
1368
|
"space-0-5": "calc(0.125rem * var(--gw-density))",
|
|
1362
1369
|
"space-1": "calc(0.25rem * var(--gw-density))",
|
|
1363
1370
|
"space-2": "calc(0.5rem * var(--gw-density))",
|
|
@@ -1530,6 +1537,7 @@ export const themes = [
|
|
|
1530
1537
|
"font-weight-regular": "400",
|
|
1531
1538
|
"font-weight-strong": "600",
|
|
1532
1539
|
"density": "1",
|
|
1540
|
+
"control-scale": "1",
|
|
1533
1541
|
"space-0-5": "calc(0.125rem * var(--gw-density))",
|
|
1534
1542
|
"space-1": "calc(0.25rem * var(--gw-density))",
|
|
1535
1543
|
"space-2": "calc(0.5rem * var(--gw-density))",
|
|
@@ -1655,6 +1663,7 @@ export const themes = [
|
|
|
1655
1663
|
"font-weight-regular": "400",
|
|
1656
1664
|
"font-weight-strong": "600",
|
|
1657
1665
|
"density": "1",
|
|
1666
|
+
"control-scale": "1",
|
|
1658
1667
|
"space-0-5": "calc(0.125rem * var(--gw-density))",
|
|
1659
1668
|
"space-1": "calc(0.25rem * var(--gw-density))",
|
|
1660
1669
|
"space-2": "calc(0.5rem * var(--gw-density))",
|
|
@@ -1827,6 +1836,7 @@ export const themes = [
|
|
|
1827
1836
|
"font-weight-regular": "400",
|
|
1828
1837
|
"font-weight-strong": "600",
|
|
1829
1838
|
"density": "1",
|
|
1839
|
+
"control-scale": "1",
|
|
1830
1840
|
"space-0-5": "calc(0.125rem * var(--gw-density))",
|
|
1831
1841
|
"space-1": "calc(0.25rem * var(--gw-density))",
|
|
1832
1842
|
"space-2": "calc(0.5rem * var(--gw-density))",
|
|
@@ -1999,6 +2009,7 @@ export const themes = [
|
|
|
1999
2009
|
"font-weight-regular": "400",
|
|
2000
2010
|
"font-weight-strong": "600",
|
|
2001
2011
|
"density": "1",
|
|
2012
|
+
"control-scale": "1",
|
|
2002
2013
|
"space-0-5": "calc(0.125rem * var(--gw-density))",
|
|
2003
2014
|
"space-1": "calc(0.25rem * var(--gw-density))",
|
|
2004
2015
|
"space-2": "calc(0.5rem * var(--gw-density))",
|
|
@@ -2171,6 +2182,7 @@ export const themes = [
|
|
|
2171
2182
|
"font-weight-regular": "400",
|
|
2172
2183
|
"font-weight-strong": "600",
|
|
2173
2184
|
"density": "1",
|
|
2185
|
+
"control-scale": "1",
|
|
2174
2186
|
"space-0-5": "calc(0.125rem * var(--gw-density))",
|
|
2175
2187
|
"space-1": "calc(0.25rem * var(--gw-density))",
|
|
2176
2188
|
"space-2": "calc(0.5rem * var(--gw-density))",
|
|
@@ -2296,6 +2308,7 @@ export const themes = [
|
|
|
2296
2308
|
"font-weight-regular": "400",
|
|
2297
2309
|
"font-weight-strong": "600",
|
|
2298
2310
|
"density": "1",
|
|
2311
|
+
"control-scale": "1",
|
|
2299
2312
|
"space-0-5": "calc(0.125rem * var(--gw-density))",
|
|
2300
2313
|
"space-1": "calc(0.25rem * var(--gw-density))",
|
|
2301
2314
|
"space-2": "calc(0.5rem * var(--gw-density))",
|
|
@@ -2468,6 +2481,7 @@ export const themes = [
|
|
|
2468
2481
|
"font-weight-regular": "400",
|
|
2469
2482
|
"font-weight-strong": "600",
|
|
2470
2483
|
"density": "1",
|
|
2484
|
+
"control-scale": "1",
|
|
2471
2485
|
"space-0-5": "calc(0.125rem * var(--gw-density))",
|
|
2472
2486
|
"space-1": "calc(0.25rem * var(--gw-density))",
|
|
2473
2487
|
"space-2": "calc(0.5rem * var(--gw-density))",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@timmo001/groundwork-tokens",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Groundwork's design tokens: the theme schema, the OKLCH solver and every theme as CSS and JSON",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
"./webmcp": "./src/webmcp.ts",
|
|
12
12
|
"./opentui": "./generated/opentui.ts",
|
|
13
13
|
"./themes.css": "./generated/themes.css",
|
|
14
|
-
"./themes.json": "./generated/themes.json"
|
|
14
|
+
"./themes.json": "./generated/themes.json",
|
|
15
|
+
"./themes/*.json": "./themes/*.json"
|
|
15
16
|
},
|
|
16
17
|
"files": [
|
|
17
18
|
"src",
|
package/src/generate.ts
CHANGED
|
@@ -32,6 +32,9 @@ const fontStack = (font: Font | MonoFont) => {
|
|
|
32
32
|
|
|
33
33
|
const density = { compact: 0.85, normal: 1, roomy: 1.2 } as const;
|
|
34
34
|
|
|
35
|
+
/** How much controls grow or shrink with density, less than spacing does. */
|
|
36
|
+
const controlScale = { compact: 0.85, normal: 1, roomy: 1.1 } as const;
|
|
37
|
+
|
|
35
38
|
const borderColor = {
|
|
36
39
|
none: "transparent",
|
|
37
40
|
hairline: "var(--gw-color-border-quiet)",
|
|
@@ -47,6 +50,7 @@ const styleProperties = (style: Style) => ({
|
|
|
47
50
|
"font-weight-regular": String(style.weights.regular),
|
|
48
51
|
"font-weight-strong": String(style.weights.strong),
|
|
49
52
|
density: String(density[style.density]),
|
|
53
|
+
"control-scale": String(controlScale[style.density]),
|
|
50
54
|
...spacing,
|
|
51
55
|
"radius-panel": `${style.radius.panel}px`,
|
|
52
56
|
"radius-control": `${style.radius.control}px`,
|
|
@@ -103,6 +107,7 @@ const spacing = {
|
|
|
103
107
|
|
|
104
108
|
const foundations = {
|
|
105
109
|
density: "1",
|
|
110
|
+
"control-scale": "1",
|
|
106
111
|
...spacing,
|
|
107
112
|
"font-size-multiplier": "1",
|
|
108
113
|
"font-size-2xs": "calc(0.6875rem * var(--gw-font-size-multiplier))",
|
|
@@ -151,40 +156,74 @@ const modeBlock = (roles: Roles, dark: boolean, indent = " ") =>
|
|
|
151
156
|
declarations({ ...colorProperties(roles), ...shadows(dark) }, indent),
|
|
152
157
|
].join("\n");
|
|
153
158
|
|
|
154
|
-
/**
|
|
155
|
-
|
|
159
|
+
/**
|
|
160
|
+
* A rule under `theme`'s selector for each of its modes, matching how
|
|
161
|
+
* `data-gw-mode` and the system's scheme pick one. `block` writes a mode's
|
|
162
|
+
* declarations at the indent it's given.
|
|
163
|
+
*/
|
|
164
|
+
export const modeRules = (
|
|
165
|
+
theme: ResolvedTheme,
|
|
166
|
+
block: (roles: Roles, dark: boolean, indent: string) => string,
|
|
167
|
+
) => {
|
|
156
168
|
const selector = `[data-gw-theme="${theme.id}"]`;
|
|
157
|
-
const style = `${selector} {\n${declarations(styleProperties(theme.style))}\n}`;
|
|
158
169
|
const { light, dark, darker } = theme.modes;
|
|
159
|
-
const
|
|
170
|
+
const rules: string[] = [];
|
|
160
171
|
|
|
161
172
|
if (light !== undefined) {
|
|
162
|
-
|
|
173
|
+
rules.push(`${selector} {\n${block(light, false, " ")}\n}`);
|
|
163
174
|
} else if (dark !== undefined) {
|
|
164
|
-
|
|
175
|
+
rules.push(`${selector} {\n${block(dark, true, " ")}\n}`);
|
|
165
176
|
}
|
|
166
177
|
|
|
167
178
|
if (dark !== undefined) {
|
|
168
|
-
|
|
169
|
-
`${selector}[data-gw-mode="dark"] {\n${
|
|
179
|
+
rules.push(
|
|
180
|
+
`${selector}[data-gw-mode="dark"] {\n${block(dark, true, " ")}\n}`,
|
|
170
181
|
);
|
|
171
182
|
|
|
172
183
|
if (light !== undefined) {
|
|
173
|
-
|
|
174
|
-
`@media (prefers-color-scheme: dark) {\n ${selector}:not([data-gw-mode]) {\n${
|
|
184
|
+
rules.push(
|
|
185
|
+
`@media (prefers-color-scheme: dark) {\n ${selector}:not([data-gw-mode]) {\n${block(dark, true, " ")}\n }\n}`,
|
|
175
186
|
);
|
|
176
187
|
}
|
|
177
188
|
}
|
|
178
189
|
|
|
179
190
|
if (darker !== undefined) {
|
|
180
|
-
|
|
181
|
-
`${selector}[data-gw-mode="darker"] {\n${
|
|
191
|
+
rules.push(
|
|
192
|
+
`${selector}[data-gw-mode="darker"] {\n${block(darker, true, " ")}\n}`,
|
|
182
193
|
);
|
|
183
194
|
}
|
|
184
195
|
|
|
185
|
-
return
|
|
196
|
+
return rules;
|
|
186
197
|
};
|
|
187
198
|
|
|
199
|
+
/** One theme's `--gw-*` rules under `[data-gw-theme]`, in each of its modes. */
|
|
200
|
+
export const themeCss = (theme: ResolvedTheme) =>
|
|
201
|
+
[
|
|
202
|
+
`[data-gw-theme="${theme.id}"] {\n${declarations(styleProperties(theme.style))}\n}`,
|
|
203
|
+
...modeRules(theme, modeBlock),
|
|
204
|
+
].join("\n\n");
|
|
205
|
+
|
|
206
|
+
/** A control height that follows the theme's density, as the elements do. */
|
|
207
|
+
const dense = (rem: number) =>
|
|
208
|
+
`calc(${Number(rem.toFixed(4))}rem * var(--gw-control-scale, 1))`;
|
|
209
|
+
|
|
210
|
+
/** Pre-upgrade heights for each size preset, matching `controlSizes`. */
|
|
211
|
+
const sized = (
|
|
212
|
+
tag: string,
|
|
213
|
+
rem: number,
|
|
214
|
+
properties: readonly string[] = ["min-block-size"],
|
|
215
|
+
) =>
|
|
216
|
+
Object.fromEntries(
|
|
217
|
+
Object.entries({ xs: 0.6, small: 0.8, large: 1.2, xl: 1.4 }).map(
|
|
218
|
+
([size, scale]) => [
|
|
219
|
+
`${tag}[size="${size}"]`,
|
|
220
|
+
Object.fromEntries(
|
|
221
|
+
properties.map((property) => [property, dense(rem * scale)]),
|
|
222
|
+
),
|
|
223
|
+
],
|
|
224
|
+
),
|
|
225
|
+
);
|
|
226
|
+
|
|
188
227
|
/**
|
|
189
228
|
* What each `gw-` element looks like before its script defines it: the
|
|
190
229
|
* display and block size it will have, so nothing moves when it upgrades.
|
|
@@ -193,34 +232,20 @@ const preUpgrade = {
|
|
|
193
232
|
"gw-fade-in": { opacity: "0" },
|
|
194
233
|
"gw-button, gw-menu-button, gw-segmented": {
|
|
195
234
|
display: "inline-block",
|
|
196
|
-
"min-block-size":
|
|
235
|
+
"min-block-size": dense(2.5),
|
|
197
236
|
"vertical-align": "middle",
|
|
198
237
|
},
|
|
199
238
|
"gw-button": {
|
|
200
239
|
"padding-inline": "calc(var(--gw-space-4) + 1px)",
|
|
201
240
|
"font-size": "var(--gw-font-size-s)",
|
|
202
241
|
"font-weight": "var(--gw-font-weight-strong)",
|
|
203
|
-
"line-height":
|
|
242
|
+
"line-height": dense(2.5),
|
|
204
243
|
"white-space": "nowrap",
|
|
205
244
|
"text-transform": "var(--gw-label-transform)",
|
|
206
245
|
"letter-spacing": "var(--gw-label-tracking)",
|
|
207
246
|
},
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
"line-height": "1.5rem",
|
|
211
|
-
},
|
|
212
|
-
'gw-button[size="small"]': {
|
|
213
|
-
"min-block-size": "2rem",
|
|
214
|
-
"line-height": "2rem",
|
|
215
|
-
},
|
|
216
|
-
'gw-button[size="large"]': {
|
|
217
|
-
"min-block-size": "3rem",
|
|
218
|
-
"line-height": "3rem",
|
|
219
|
-
},
|
|
220
|
-
'gw-button[size="xl"]': {
|
|
221
|
-
"min-block-size": "3.5rem",
|
|
222
|
-
"line-height": "3.5rem",
|
|
223
|
-
},
|
|
247
|
+
...sized("gw-button", 2.5, ["min-block-size", "line-height"]),
|
|
248
|
+
...sized("gw-menu-button", 2.5),
|
|
224
249
|
"gw-card": {
|
|
225
250
|
display: "block",
|
|
226
251
|
padding: "var(--gw-space-4)",
|
|
@@ -264,9 +289,10 @@ const preUpgrade = {
|
|
|
264
289
|
"margin-inline-end": "var(--gw-space-2)",
|
|
265
290
|
"vertical-align": "middle",
|
|
266
291
|
},
|
|
267
|
-
"gw-chip": { display: "inline-flex", "min-block-size":
|
|
268
|
-
"gw-
|
|
269
|
-
|
|
292
|
+
"gw-chip": { display: "inline-flex", "min-block-size": dense(2) },
|
|
293
|
+
...sized("gw-chip", 2),
|
|
294
|
+
"gw-badge": { display: "inline-flex", "min-block-size": dense(2.25) },
|
|
295
|
+
...sized("gw-badge", 2.25),
|
|
270
296
|
"gw-dot": {
|
|
271
297
|
display: "inline-block",
|
|
272
298
|
"inline-size": "0.5rem",
|
|
@@ -283,12 +309,15 @@ const preUpgrade = {
|
|
|
283
309
|
display: "inline-flex",
|
|
284
310
|
"min-block-size": "1.25rem",
|
|
285
311
|
},
|
|
286
|
-
"gw-input, gw-select": {
|
|
312
|
+
"gw-input, gw-select": {
|
|
313
|
+
display: "flex",
|
|
314
|
+
"min-block-size": `calc(2rem + ${dense(2.5)})`,
|
|
315
|
+
},
|
|
287
316
|
"gw-input:is([hint], [error]), gw-select:is([hint], [error])": {
|
|
288
|
-
"min-block-size":
|
|
317
|
+
"min-block-size": `calc(3.75rem + ${dense(2.5)})`,
|
|
289
318
|
},
|
|
290
319
|
"gw-select:is([label-hidden], [inline-label])": {
|
|
291
|
-
"min-block-size":
|
|
320
|
+
"min-block-size": dense(2.5),
|
|
292
321
|
},
|
|
293
322
|
"gw-select[inline-label]": { display: "inline-flex" },
|
|
294
323
|
"gw-checkbox, gw-switch": { display: "flex", "min-block-size": "1.5rem" },
|
package/src/index.ts
CHANGED
package/src/page.ts
CHANGED
|
@@ -79,6 +79,12 @@ export interface PageThemeOptions {
|
|
|
79
79
|
readonly defaultMode?: ThemeMode;
|
|
80
80
|
/** The element the attributes go on. Defaults to `<html>`. */
|
|
81
81
|
readonly root?: HTMLElement;
|
|
82
|
+
/**
|
|
83
|
+
* The app's own tones, solved into an imported theme's CSS beside its
|
|
84
|
+
* roles. The built-in themes' tones come from `appTones` in the runtime
|
|
85
|
+
* entry, on the page with their CSS.
|
|
86
|
+
*/
|
|
87
|
+
readonly tones?: Readonly<Record<string, string>>;
|
|
82
88
|
}
|
|
83
89
|
|
|
84
90
|
export interface PageTheme {
|
|
@@ -210,12 +216,17 @@ export const pageTheme = (options: PageThemeOptions): PageTheme => {
|
|
|
210
216
|
|
|
211
217
|
/** Solves a document under the custom id, applies it and keeps it. */
|
|
212
218
|
const applyCustom = async (document: Theme, text: string) => {
|
|
213
|
-
const { runtimeTheme } = await import("./runtime.ts");
|
|
219
|
+
const { appTonesCss, runtimeTheme } = await import("./runtime.ts");
|
|
214
220
|
const runtime = runtimeTheme(document, customThemeId);
|
|
215
221
|
|
|
216
|
-
|
|
222
|
+
const css =
|
|
223
|
+
options.tones === undefined
|
|
224
|
+
? runtime.css
|
|
225
|
+
: `${runtime.css}\n\n${appTonesCss(options.tones, runtime.theme)}`;
|
|
226
|
+
|
|
227
|
+
setStyle(css);
|
|
217
228
|
write(stored.document, text);
|
|
218
|
-
write(stored.css,
|
|
229
|
+
write(stored.css, css);
|
|
219
230
|
write(stored.name, document.name);
|
|
220
231
|
write(stored.theme, customThemeId);
|
|
221
232
|
commit({ ...state, theme: customThemeId, custom: document.name });
|
package/src/runtime.ts
CHANGED
|
@@ -10,9 +10,12 @@ import baseDocument from "../themes/base.json" with { type: "json" };
|
|
|
10
10
|
import { themeCss } from "./generate.ts";
|
|
11
11
|
import { SolvedTheme, Theme } from "./schema.ts";
|
|
12
12
|
import { check, resolve, type Check, type ResolvedTheme } from "./solve.ts";
|
|
13
|
+
import { appTonesCss, type AppTones } from "./tones.ts";
|
|
13
14
|
|
|
14
15
|
export { omarchyTheme } from "./omarchy.ts";
|
|
15
16
|
|
|
17
|
+
export { appTonesCss, type AppTones } from "./tones.ts";
|
|
18
|
+
|
|
16
19
|
const base = Schema.decodeUnknownSync(SolvedTheme)(baseDocument);
|
|
17
20
|
|
|
18
21
|
/** A theme solved at runtime, with its CSS and every contrast check. */
|
|
@@ -37,6 +40,21 @@ export const runtimeTheme = (theme: Theme, id = theme.id): RuntimeTheme => {
|
|
|
37
40
|
return { theme: resolved, css: themeCss(resolved), checks: check(resolved) };
|
|
38
41
|
};
|
|
39
42
|
|
|
43
|
+
/**
|
|
44
|
+
* An app's own tones as CSS for each of `themes`: `--app-tone-<name>`,
|
|
45
|
+
* `-fill` and `-border`, solved against each theme's surfaces in every mode
|
|
46
|
+
* so they meet the status colors' contrast. Put it beside the themes' CSS,
|
|
47
|
+
* such as at build time, then point a component's tone at one:
|
|
48
|
+
*
|
|
49
|
+
* ```css
|
|
50
|
+
* .regressed { --gw-tone: var(--app-tone-regressed); }
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
export const appTones = (tones: AppTones, themes: readonly Theme[]) =>
|
|
54
|
+
themes
|
|
55
|
+
.map((theme) => appTonesCss(tones, resolve(theme, base.style)))
|
|
56
|
+
.join("\n\n");
|
|
57
|
+
|
|
40
58
|
/**
|
|
41
59
|
* Where an app keeps a user's theme document. The document is stored, not
|
|
42
60
|
* its CSS, so it's solved again when the solver changes. Local storage is
|
package/src/tones.ts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* App tones: an app's own state colors, such as an issue's "regressed" or
|
|
3
|
+
* "muted", solved against each theme's surfaces the way the status colors
|
|
4
|
+
* are, so they read in every theme and mode.
|
|
5
|
+
*
|
|
6
|
+
* @module
|
|
7
|
+
*/
|
|
8
|
+
import {
|
|
9
|
+
contrast,
|
|
10
|
+
fromHex,
|
|
11
|
+
solveLightness,
|
|
12
|
+
toCss,
|
|
13
|
+
withAlpha,
|
|
14
|
+
type Oklch,
|
|
15
|
+
} from "./color.ts";
|
|
16
|
+
import { modeRules } from "./generate.ts";
|
|
17
|
+
import { targets, type ResolvedTheme, type Roles } from "./solve.ts";
|
|
18
|
+
|
|
19
|
+
/** An app's tones: each name and the hex color it starts from. */
|
|
20
|
+
export type AppTones = Readonly<Record<string, string>>;
|
|
21
|
+
|
|
22
|
+
const textSurfaces = [
|
|
23
|
+
"surface-lower",
|
|
24
|
+
"surface-low",
|
|
25
|
+
"surface-default",
|
|
26
|
+
"surface-raised",
|
|
27
|
+
"surface-overlay",
|
|
28
|
+
] as const;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Each tone in one mode: its text color, kept as given where it already meets
|
|
32
|
+
* the status contrast target on every surface and moved lighter or darker
|
|
33
|
+
* until it does where not, with a quiet fill and a border from it.
|
|
34
|
+
*/
|
|
35
|
+
export const appToneRoles = (
|
|
36
|
+
tones: AppTones,
|
|
37
|
+
roles: Roles,
|
|
38
|
+
dark: boolean,
|
|
39
|
+
): Roles =>
|
|
40
|
+
Object.fromEntries(
|
|
41
|
+
Object.entries(tones).flatMap(([name, hex]) => {
|
|
42
|
+
const seed = fromHex(hex);
|
|
43
|
+
|
|
44
|
+
const surfaces = textSurfaces.flatMap((surface) => {
|
|
45
|
+
const color = roles[surface];
|
|
46
|
+
|
|
47
|
+
return color === undefined ? [] : [color];
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// Where the tone reads worst
|
|
51
|
+
const ground = surfaces.reduce<Oklch | undefined>(
|
|
52
|
+
(worst, surface) =>
|
|
53
|
+
worst === undefined || contrast(seed, surface) < contrast(seed, worst)
|
|
54
|
+
? surface
|
|
55
|
+
: worst,
|
|
56
|
+
undefined,
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
const text =
|
|
60
|
+
ground === undefined || contrast(seed, ground) >= targets.status
|
|
61
|
+
? seed
|
|
62
|
+
: solveLightness(
|
|
63
|
+
seed,
|
|
64
|
+
ground,
|
|
65
|
+
targets.status,
|
|
66
|
+
dark ? "lighter" : "darker",
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
return [
|
|
70
|
+
[name, text],
|
|
71
|
+
[`${name}-fill`, withAlpha(text, 0.14)],
|
|
72
|
+
[`${name}-border`, withAlpha(text, 0.45)],
|
|
73
|
+
];
|
|
74
|
+
}),
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* `--app-tone-<name>`, `-fill` and `-border` for each tone, under the same
|
|
79
|
+
* selectors as `theme`'s own CSS. Set a component's `--gw-tone`,
|
|
80
|
+
* `--gw-tone-fill` and `--gw-tone-border` from them.
|
|
81
|
+
*/
|
|
82
|
+
export const appTonesCss = (tones: AppTones, theme: ResolvedTheme) =>
|
|
83
|
+
modeRules(theme, (roles, dark, indent) =>
|
|
84
|
+
Object.entries(appToneRoles(tones, roles, dark))
|
|
85
|
+
.map(([name, color]) => `${indent}--app-tone-${name}: ${toCss(color)};`)
|
|
86
|
+
.join("\n"),
|
|
87
|
+
).join("\n\n");
|