@astryxdesign/theme-butter 0.7.5 → 0.7.6-canary.00146a7

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/butter.d.ts CHANGED
@@ -2,8 +2,8 @@
2
2
  * @generated by `astryx theme build` — do not edit manually.
3
3
  * Source: src/butterTheme.ts
4
4
  * Command: astryx theme build src/butterTheme.ts --out dist/theme.css
5
- * CLI: @astryxdesign/cli@0.7.5
6
- * Core: @astryxdesign/core@0.7.5
5
+ * CLI: @astryxdesign/cli@0.7.6
6
+ * Core: @astryxdesign/core@0.7.6
7
7
  */
8
8
 
9
9
  /// <reference path="./butter.variants.d.ts" />
package/dist/butter.js CHANGED
@@ -2,8 +2,8 @@
2
2
  * @generated by `astryx theme build` — do not edit manually.
3
3
  * Source: src/butterTheme.ts
4
4
  * Command: astryx theme build src/butterTheme.ts --out dist/theme.css
5
- * CLI: @astryxdesign/cli@0.7.5
6
- * Core: @astryxdesign/core@0.7.5
5
+ * CLI: @astryxdesign/cli@0.7.6
6
+ * Core: @astryxdesign/core@0.7.6
7
7
  */
8
8
 
9
9
  import { butterIconRegistry } from "./icons.mjs";
@@ -81,6 +81,15 @@ export const butterTheme = {
81
81
  "--duration-slow-min": "525ms",
82
82
  "--duration-slow": "700ms",
83
83
  "--duration-slow-max": "935ms",
84
+ "--_astryx-pre-tempo-duration-fast-min": "95ms",
85
+ "--_astryx-pre-tempo-duration-fast": "125ms",
86
+ "--_astryx-pre-tempo-duration-fast-max": "165ms",
87
+ "--_astryx-pre-tempo-duration-medium-min": "225ms",
88
+ "--_astryx-pre-tempo-duration-medium": "300ms",
89
+ "--_astryx-pre-tempo-duration-medium-max": "400ms",
90
+ "--_astryx-pre-tempo-duration-slow-min": "525ms",
91
+ "--_astryx-pre-tempo-duration-slow": "700ms",
92
+ "--_astryx-pre-tempo-duration-slow-max": "935ms",
84
93
  "--font-family-body": "Outfit, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif",
85
94
  "--font-family-heading": "Outfit, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif",
86
95
  "--font-family-code": "\"JetBrains Mono\", \"SF Mono\", Monaco, Consolas, monospace",
@@ -2,8 +2,8 @@
2
2
  * @generated by `astryx theme build` — do not edit manually.
3
3
  * Source: src/butterTheme.ts
4
4
  * Command: astryx theme build src/butterTheme.ts --out dist/theme.css
5
- * CLI: @astryxdesign/cli@0.7.5
6
- * Core: @astryxdesign/core@0.7.5
5
+ * CLI: @astryxdesign/cli@0.7.6
6
+ * Core: @astryxdesign/core@0.7.6
7
7
  */
8
8
 
9
9
  // Generated by astryx theme build
package/dist/theme.css CHANGED
@@ -2,8 +2,8 @@
2
2
  * @generated by `astryx theme build` — do not edit manually.
3
3
  * Source: src/butterTheme.ts
4
4
  * Command: astryx theme build src/butterTheme.ts --out dist/theme.css
5
- * CLI: @astryxdesign/cli@0.7.5
6
- * Core: @astryxdesign/core@0.7.5
5
+ * CLI: @astryxdesign/cli@0.7.6
6
+ * Core: @astryxdesign/core@0.7.6
7
7
  */
8
8
 
9
9
  @layer reset, astryx-base, astryx-theme;
@@ -149,6 +149,15 @@
149
149
  --duration-slow-min: 525ms;
150
150
  --duration-slow: 700ms;
151
151
  --duration-slow-max: 935ms;
152
+ --_astryx-pre-tempo-duration-fast-min: 95ms;
153
+ --_astryx-pre-tempo-duration-fast: 125ms;
154
+ --_astryx-pre-tempo-duration-fast-max: 165ms;
155
+ --_astryx-pre-tempo-duration-medium-min: 225ms;
156
+ --_astryx-pre-tempo-duration-medium: 300ms;
157
+ --_astryx-pre-tempo-duration-medium-max: 400ms;
158
+ --_astryx-pre-tempo-duration-slow-min: 525ms;
159
+ --_astryx-pre-tempo-duration-slow: 700ms;
160
+ --_astryx-pre-tempo-duration-slow-max: 935ms;
152
161
  --font-family-body: Outfit, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
153
162
  --font-family-heading: Outfit, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
154
163
  --font-family-code: "JetBrains Mono", "SF Mono", Monaco, Consolas, monospace;
@@ -2,8 +2,8 @@
2
2
  * @generated by `astryx theme build` — do not edit manually.
3
3
  * Source: src/butterTheme.ts
4
4
  * Command: astryx theme build src/butterTheme.ts --out dist/theme.css
5
- * CLI: @astryxdesign/cli@0.7.5
6
- * Core: @astryxdesign/core@0.7.5
5
+ * CLI: @astryxdesign/cli@0.7.6
6
+ * Core: @astryxdesign/core@0.7.6
7
7
  */
8
8
 
9
9
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astryxdesign/theme-butter",
3
- "version": "0.7.5",
3
+ "version": "0.7.6-canary.00146a7",
4
4
  "displayName": "Butter Theme",
5
5
  "private": false,
6
6
  "description": "Warm, creamy yellows with a friendly blue accent. Playful enough for consumer surfaces, soft enough to stay readable.",
@@ -52,20 +52,34 @@
52
52
  "src",
53
53
  "palette.config.json",
54
54
  "fonts.css",
55
- "fonts.css.d.ts"
55
+ "fonts.css.d.ts",
56
+ "!**/*.test.*",
57
+ "!**/*.spec.js",
58
+ "!**/*.spec.jsx",
59
+ "!**/*.spec.mjs",
60
+ "!**/*.spec.cjs",
61
+ "!**/*.spec.ts",
62
+ "!**/*.spec.tsx",
63
+ "!**/*.spec.mts",
64
+ "!**/*.spec.cts",
65
+ "!**/*.spec.d.ts",
66
+ "!**/__tests__/**",
67
+ "!**/__mocks__/**",
68
+ "!**/*.bench.*"
56
69
  ],
57
70
  "dependencies": {
58
71
  "lucide-react": "^1.18.0"
59
72
  },
60
73
  "peerDependencies": {
61
- "@astryxdesign/core": "0.7.5",
74
+ "@astryxdesign/core": "0.7.6-canary.00146a7",
62
75
  "react": ">=19"
63
76
  },
64
77
  "devDependencies": {
65
- "@astryxdesign/cli": "0.7.5"
78
+ "@astryxdesign/cli": "0.7.6-canary.00146a7"
66
79
  },
67
80
  "module": "./dist/source.mjs",
68
81
  "scripts": {
82
+ "api:report": "node ../../../scripts/api-report/cli.mjs --package .",
69
83
  "build": "node ../../../scripts/clean-dist.mjs && node ../../../scripts/generate-butter-palette-refs.mjs --check && astryx theme build src/butterTheme.ts -o dist/theme.css --icons-specifier ./icons.mjs && tsup && tsc --project tsconfig.build.json && node ../../../scripts/check-fully-specified.mjs"
70
84
  }
71
85
  }
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=butterColorMapping.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"butterColorMapping.test.d.ts","sourceRoot":"","sources":["../src/butterColorMapping.test.ts"],"names":[],"mappings":""}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=butterPalettes.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"butterPalettes.test.d.ts","sourceRoot":"","sources":["../src/butterPalettes.test.ts"],"names":[],"mappings":""}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=butterTheme.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"butterTheme.test.d.ts","sourceRoot":"","sources":["../src/butterTheme.test.ts"],"names":[],"mappings":""}
@@ -1,328 +0,0 @@
1
- // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
-
3
- exports[`butter palette artifact > matches the complete released legacy object 1`] = `
4
- {
5
- "accent": {
6
- "0": "#000000",
7
- "10": "#00136c",
8
- "100": "#ffffff",
9
- "15": "#001c7e",
10
- "20": "#002592",
11
- "25": "#002fa7",
12
- "30": "#0039be",
13
- "35": "#0043d7",
14
- "40": "#004df0",
15
- "45": "#0759ff",
16
- "5": "#00085e",
17
- "50": "#4a67ff",
18
- "55": "#6875ff",
19
- "60": "#8083ff",
20
- "65": "#9492ff",
21
- "70": "#a6a1ff",
22
- "75": "#b6b0ff",
23
- "80": "#c6bfff",
24
- "85": "#d5cfff",
25
- "90": "#e3dfff",
26
- "95": "#f1efff",
27
- },
28
- "blue": {
29
- "0": "#000000",
30
- "10": "#001b4c",
31
- "100": "#ffffff",
32
- "15": "#002558",
33
- "20": "#062f63",
34
- "25": "#203a6c",
35
- "30": "#324575",
36
- "35": "#41517d",
37
- "40": "#505d86",
38
- "45": "#5f698f",
39
- "5": "#001041",
40
- "50": "#6d7698",
41
- "55": "#7a82a6",
42
- "60": "#878fb3",
43
- "65": "#949cc1",
44
- "70": "#a2aacf",
45
- "75": "#afb7dd",
46
- "80": "#bdc5eb",
47
- "85": "#cbd3f9",
48
- "90": "#dbe1ff",
49
- "95": "#edf0ff",
50
- },
51
- "cyan": {
52
- "0": "#000000",
53
- "10": "#00262a",
54
- "100": "#ffffff",
55
- "15": "#003034",
56
- "20": "#003a3e",
57
- "25": "#004649",
58
- "30": "#005255",
59
- "35": "#005e61",
60
- "40": "#006a6d",
61
- "45": "#1f7678",
62
- "5": "#001d1e",
63
- "50": "#3c8183",
64
- "55": "#4a8e90",
65
- "60": "#579c9d",
66
- "65": "#65a9aa",
67
- "70": "#72b7b8",
68
- "75": "#80c4c5",
69
- "80": "#8dd2d3",
70
- "85": "#9be0e1",
71
- "90": "#a9eff0",
72
- "95": "#b7fdfe",
73
- },
74
- "error": {
75
- "0": "#000000",
76
- "10": "#530000",
77
- "100": "#ffffff",
78
- "15": "#600000",
79
- "20": "#6d0000",
80
- "25": "#771210",
81
- "30": "#82261e",
82
- "35": "#8c372c",
83
- "40": "#96463b",
84
- "45": "#a0564a",
85
- "5": "#470000",
86
- "50": "#a96559",
87
- "55": "#b77265",
88
- "60": "#c57e72",
89
- "65": "#d48b7e",
90
- "70": "#e2998b",
91
- "75": "#f1a698",
92
- "80": "#ffb4a6",
93
- "85": "#ffc7bc",
94
- "90": "#ffdad2",
95
- "95": "#ffece8",
96
- },
97
- "green": {
98
- "0": "#000000",
99
- "10": "#002800",
100
- "100": "#ffffff",
101
- "15": "#003100",
102
- "20": "#003c00",
103
- "25": "#004800",
104
- "30": "#01530d",
105
- "35": "#1f5f1f",
106
- "40": "#346a30",
107
- "45": "#467640",
108
- "5": "#001f00",
109
- "50": "#578151",
110
- "55": "#648e5d",
111
- "60": "#709c6a",
112
- "65": "#7da976",
113
- "70": "#8ab783",
114
- "75": "#98c490",
115
- "80": "#a5d29d",
116
- "85": "#b3e0ab",
117
- "90": "#c1efb8",
118
- "95": "#cffdc6",
119
- },
120
- "neutral": {
121
- "0": "#000000",
122
- "10": "#101c2f",
123
- "100": "#ffffff",
124
- "15": "#1b263a",
125
- "20": "#273045",
126
- "25": "#333b4f",
127
- "30": "#3f4759",
128
- "35": "#4b5264",
129
- "40": "#585e6f",
130
- "45": "#656a79",
131
- "5": "#051124",
132
- "50": "#727784",
133
- "55": "#7f8491",
134
- "60": "#8c909f",
135
- "65": "#999eac",
136
- "70": "#a6abba",
137
- "75": "#b4b9c7",
138
- "80": "#c1c6d5",
139
- "85": "#cfd4e3",
140
- "90": "#dde2f2",
141
- "95": "#ebf0ff",
142
- },
143
- "orange": {
144
- "0": "#000000",
145
- "10": "#381200",
146
- "100": "#ffffff",
147
- "15": "#461b00",
148
- "20": "#542400",
149
- "25": "#622e00",
150
- "30": "#6d3a00",
151
- "35": "#794700",
152
- "40": "#845406",
153
- "45": "#906121",
154
- "5": "#2d0600",
155
- "50": "#9b6e36",
156
- "55": "#a97b42",
157
- "60": "#b7874e",
158
- "65": "#c6945b",
159
- "70": "#d4a267",
160
- "75": "#e3af74",
161
- "80": "#f2bd81",
162
- "85": "#ffcb8e",
163
- "90": "#ffdcb6",
164
- "95": "#ffedda",
165
- },
166
- "pink": {
167
- "0": "#000000",
168
- "10": "#490048",
169
- "100": "#ffffff",
170
- "15": "#560054",
171
- "20": "#62005f",
172
- "25": "#6c0a68",
173
- "30": "#762371",
174
- "35": "#80357a",
175
- "40": "#894583",
176
- "45": "#93558c",
177
- "5": "#3c003d",
178
- "50": "#9c6496",
179
- "55": "#aa71a3",
180
- "60": "#b77eb0",
181
- "65": "#c58bbe",
182
- "70": "#d398cc",
183
- "75": "#e2a6da",
184
- "80": "#f0b3e8",
185
- "85": "#ffc1f6",
186
- "90": "#ffd5fb",
187
- "95": "#ffeafd",
188
- },
189
- "purple": {
190
- "0": "#000000",
191
- "10": "#2b005c",
192
- "100": "#ffffff",
193
- "15": "#390268",
194
- "20": "#461373",
195
- "25": "#52237b",
196
- "30": "#5d3283",
197
- "35": "#69408b",
198
- "40": "#744e92",
199
- "45": "#7f5c9a",
200
- "5": "#1e004f",
201
- "50": "#8b6aa2",
202
- "55": "#9877b0",
203
- "60": "#a584bd",
204
- "65": "#b391cb",
205
- "70": "#c19ed9",
206
- "75": "#cfabe8",
207
- "80": "#ddb9f6",
208
- "85": "#eac8ff",
209
- "90": "#f2daff",
210
- "95": "#f9ecff",
211
- },
212
- "red": {
213
- "0": "#000000",
214
- "10": "#490000",
215
- "100": "#ffffff",
216
- "15": "#550000",
217
- "20": "#62100f",
218
- "25": "#6d211c",
219
- "30": "#773029",
220
- "35": "#823f36",
221
- "40": "#8c4d44",
222
- "45": "#955b52",
223
- "5": "#3e0000",
224
- "50": "#9f6961",
225
- "55": "#ad766d",
226
- "60": "#bb837a",
227
- "65": "#c99087",
228
- "70": "#d79d94",
229
- "75": "#e6aba1",
230
- "80": "#f4b8ae",
231
- "85": "#ffc7bd",
232
- "90": "#ffdad3",
233
- "95": "#ffece8",
234
- },
235
- "success": {
236
- "0": "#000000",
237
- "10": "#092300",
238
- "100": "#ffffff",
239
- "15": "#0b2e00",
240
- "20": "#043b00",
241
- "25": "#004700",
242
- "30": "#005400",
243
- "35": "#036100",
244
- "40": "#136e00",
245
- "45": "#277b00",
246
- "5": "#001a00",
247
- "50": "#448700",
248
- "55": "#529400",
249
- "60": "#60a105",
250
- "65": "#6eaf1d",
251
- "70": "#7cbd2e",
252
- "75": "#8bcb3c",
253
- "80": "#99d94b",
254
- "85": "#a7e758",
255
- "90": "#b5f566",
256
- "95": "#ccff88",
257
- },
258
- "teal": {
259
- "0": "#000000",
260
- "10": "#00280b",
261
- "100": "#ffffff",
262
- "15": "#003216",
263
- "20": "#003d22",
264
- "25": "#00482d",
265
- "30": "#005439",
266
- "35": "#005f45",
267
- "40": "#136b52",
268
- "45": "#30775f",
269
- "5": "#001f00",
270
- "50": "#46826d",
271
- "55": "#528f79",
272
- "60": "#5f9d86",
273
- "65": "#6caa93",
274
- "70": "#7ab8a0",
275
- "75": "#87c5ae",
276
- "80": "#94d3bb",
277
- "85": "#a2e1c9",
278
- "90": "#b0f0d7",
279
- "95": "#befee5",
280
- },
281
- "warning": {
282
- "0": "#000000",
283
- "10": "#301800",
284
- "100": "#ffffff",
285
- "15": "#3b2200",
286
- "20": "#472c00",
287
- "25": "#543700",
288
- "30": "#614200",
289
- "35": "#6f4d00",
290
- "40": "#7d5800",
291
- "45": "#8b6400",
292
- "5": "#270c00",
293
- "50": "#9a7000",
294
- "55": "#a97d00",
295
- "60": "#b88900",
296
- "65": "#c89600",
297
- "70": "#d8a300",
298
- "75": "#e7b100",
299
- "80": "#f7be00",
300
- "85": "#ffcd51",
301
- "90": "#ffde9c",
302
- "95": "#ffeed0",
303
- },
304
- "yellow": {
305
- "0": "#000000",
306
- "10": "#271c00",
307
- "100": "#ffffff",
308
- "15": "#2e2700",
309
- "20": "#373200",
310
- "25": "#413e00",
311
- "30": "#4c4a00",
312
- "35": "#575600",
313
- "40": "#646200",
314
- "45": "#726e00",
315
- "5": "#1e1200",
316
- "50": "#817a00",
317
- "55": "#8e860e",
318
- "60": "#9c9320",
319
- "65": "#aba02f",
320
- "70": "#b9ae3d",
321
- "75": "#c7bb4a",
322
- "80": "#d6c957",
323
- "85": "#e5d765",
324
- "90": "#f4e572",
325
- "95": "#fff294",
326
- },
327
- }
328
- `;
@@ -1,64 +0,0 @@
1
- // Copyright (c) Meta Platforms, Inc. and affiliates.
2
-
3
- import {describe, expect, it} from 'vitest';
4
- import {resolveThemeTokens} from '@astryxdesign/core/theme';
5
- import {palette as butterModePalettes} from './butterPalettes.generated';
6
- import {butterTheme} from './butterTheme';
7
-
8
- const categoricalFamilies = [
9
- 'blue',
10
- 'cyan',
11
- 'orange',
12
- 'pink',
13
- 'purple',
14
- 'red',
15
- 'teal',
16
- 'yellow',
17
- ] as const;
18
-
19
- describe('butter palette mapping', () => {
20
- it('preserves the signature accents and warm body surfaces', () => {
21
- const light = resolveThemeTokens(butterTheme, {mode: 'light'});
22
- const dark = resolveThemeTokens(butterTheme, {mode: 'dark'});
23
- expect(light['--color-accent']).toBe(butterModePalettes.accent.light[40]);
24
- expect(dark['--color-accent']).toBe(butterModePalettes.yellow.dark[90]);
25
- expect(light['--color-background-body']).toBe(
26
- butterModePalettes.neutral.light[95],
27
- );
28
- expect(dark['--color-background-body']).toBe(
29
- butterModePalettes.neutral.dark[10],
30
- );
31
- });
32
-
33
- it.each(['light', 'dark'] as const)(
34
- 'maps categorical roles to reviewed %s stops',
35
- mode => {
36
- const tokens = resolveThemeTokens(butterTheme, {mode});
37
- for (const family of categoricalFamilies) {
38
- const ramp = butterModePalettes[family][mode];
39
- const backgroundStop = family === 'yellow' ? 85 : 90;
40
- const borderStop = family === 'yellow' ? 70 : 80;
41
- const foregroundStop = 25;
42
- expect(tokens[`--color-background-${family}`]).toBe(
43
- ramp[backgroundStop],
44
- );
45
- expect(tokens[`--color-border-${family}`]).toBe(ramp[borderStop]);
46
- expect(tokens[`--color-icon-${family}`]).toBe(ramp[foregroundStop]);
47
- expect(tokens[`--color-text-${family}`]).toBe(ramp[foregroundStop]);
48
- }
49
- },
50
- );
51
-
52
- it('uses one smooth Green family for categorical and success roles', () => {
53
- const light = resolveThemeTokens(butterTheme, {mode: 'light'});
54
- const dark = resolveThemeTokens(butterTheme, {mode: 'dark'});
55
- expect(light['--color-success']).toBe(butterModePalettes.green.light[25]);
56
- expect(dark['--color-success']).toBe(butterModePalettes.green.dark[70]);
57
- expect(light['--color-background-green']).toBe(
58
- butterModePalettes.green.light[90],
59
- );
60
- expect(dark['--color-background-green']).toBe(
61
- butterModePalettes.green.dark[90],
62
- );
63
- });
64
- });
@@ -1,66 +0,0 @@
1
- // Copyright (c) Meta Platforms, Inc. and affiliates.
2
-
3
- import {describe, expect, it} from 'vitest';
4
- import {palette as butterModePalettes} from './butterPalettes.generated';
5
- import {butterPalettes} from './butterTheme';
6
-
7
- const stops = [
8
- 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95,
9
- 100,
10
- ] as const;
11
- const families = [
12
- 'neutral',
13
- 'accent',
14
- 'blue',
15
- 'cyan',
16
- 'green',
17
- 'orange',
18
- 'pink',
19
- 'purple',
20
- 'red',
21
- 'teal',
22
- 'yellow',
23
- ] as const;
24
-
25
- const relativeLuminance = (hex: string): number => {
26
- const channels = hex
27
- .slice(1)
28
- .match(/.{2}/g)!
29
- .map(channel => Number.parseInt(channel, 16) / 255)
30
- .map(channel =>
31
- channel <= 0.04045 ? channel / 12.92 : ((channel + 0.055) / 1.055) ** 2.4,
32
- );
33
- return channels[0] * 0.2126 + channels[1] * 0.7152 + channels[2] * 0.0722;
34
- };
35
-
36
- describe('butter palette artifact', () => {
37
- it('contains complete monotonic light and dark ramps', () => {
38
- expect(new Set(Object.keys(butterModePalettes))).toEqual(new Set(families));
39
- for (const familyName of families) {
40
- const family = butterModePalettes[familyName];
41
- for (const mode of ['light', 'dark'] as const) {
42
- const values = stops.map(stop => family[mode][stop]);
43
- expect(values.every(value => /^#[0-9a-f]{6}$/i.test(value))).toBe(true);
44
- expect(values[0]).toBe('#000000');
45
- expect(values.at(-1)).toBe('#ffffff');
46
- const luminance = values.map(relativeLuminance);
47
- expect(
48
- luminance.every(
49
- (value, index) => index === 0 || value > luminance[index - 1],
50
- ),
51
- ).toBe(true);
52
- }
53
- }
54
- });
55
-
56
- it('keeps Butter signature colors and warm surfaces exact', () => {
57
- expect(butterModePalettes.accent.light[40]).toBe('#225bff');
58
- expect(butterModePalettes.yellow.dark[90]).toBe('#fdee8c');
59
- expect(butterModePalettes.neutral.light[95]).toBe('#fdfbe4');
60
- expect(butterModePalettes.neutral.dark[10]).toBe('#261a13');
61
- });
62
-
63
- it('matches the complete released legacy object', () => {
64
- expect(butterPalettes).toMatchSnapshot();
65
- });
66
- });
@@ -1,181 +0,0 @@
1
- // Copyright (c) Meta Platforms, Inc. and affiliates.
2
-
3
- import {readFileSync} from 'node:fs';
4
- import {describe, expect, it} from 'vitest';
5
- import {generateThemeCSS} from '@astryxdesign/core/theme';
6
- import {palette as butterModePalettes} from './butterPalettes.generated';
7
- import {butterTheme} from './butterTheme';
8
-
9
- function linearize(channel: number): number {
10
- const value = channel / 255;
11
- return value <= 0.04045
12
- ? value / 12.92
13
- : Math.pow((value + 0.055) / 1.055, 2.4);
14
- }
15
-
16
- function luminance(color: string): number {
17
- const [red, green, blue] = [1, 3, 5].map(index =>
18
- Number.parseInt(color.slice(index, index + 2), 16),
19
- );
20
- return (
21
- 0.2126 * linearize(red) +
22
- 0.7152 * linearize(green) +
23
- 0.0722 * linearize(blue)
24
- );
25
- }
26
-
27
- function contrast(foreground: string, background: string): number {
28
- const [lighter, darker] = [luminance(foreground), luminance(background)].sort(
29
- (left, right) => right - left,
30
- );
31
- return (lighter + 0.05) / (darker + 0.05);
32
- }
33
-
34
- const source = readFileSync(
35
- new URL('./butterTheme.ts', import.meta.url),
36
- 'utf8',
37
- );
38
- const maintainedThemeSource = source.slice(
39
- 0,
40
- source.indexOf('/**\n * Frozen released compatibility palettes'),
41
- );
42
-
43
- describe('butter touch + narrow type pin', () => {
44
- it('floors body to 16px and holds Display 1 at its desktop size', () => {
45
- const rule = butterTheme.__adaptationRules?.[0];
46
-
47
- expect(butterTheme.__adaptations.rules).toHaveLength(1);
48
- expect(rule?.when).toEqual({pointer: 'coarse', width: {below: 'lg'}});
49
- expect(rule?.query).toBe('(width < 1024px) and (pointer: coarse)');
50
- expect(rule?.tokens['--font-size-base']).toBe('1rem');
51
- expect(rule?.tokens['--font-size-lg']).toBe('1.25rem');
52
- expect(rule?.tokens['--font-size-5xl']).toBe('3.3125rem');
53
- expect(butterTheme.tokens['--font-size-base']).toBe('0.875rem');
54
- expect(butterTheme.tokens['--font-size-5xl']).toBe('3.3125rem');
55
- expect(generateThemeCSS(butterTheme).component).toContain(
56
- '@media (width < 1024px) and (pointer: coarse)',
57
- );
58
- });
59
- });
60
-
61
- describe('butter input status roles', () => {
62
- it('keeps bright per-input status rims and glyphs on the border and icon roles', () => {
63
- const inputs = [
64
- 'text-input',
65
- 'text-area',
66
- 'number-input',
67
- 'date-input',
68
- 'time-input',
69
- 'selector',
70
- 'multi-selector',
71
- 'typeahead',
72
- 'tokenizer',
73
- ];
74
-
75
- const {green, red, yellow} = butterModePalettes;
76
- for (const input of inputs) {
77
- const component = butterTheme.components![input];
78
- expect(component['status:success']).toMatchObject({
79
- '--color-border-success': `light-dark(${green.light[55]}, ${green.light[70]})`,
80
- '--color-icon-success': `light-dark(${green.light[55]}, ${green.light[70]})`,
81
- });
82
- expect(component['status:warning']).toMatchObject({
83
- '--color-border-warning': `light-dark(${yellow.light[55]}, ${yellow.light[80]})`,
84
- '--color-icon-warning': `light-dark(${yellow.light[55]}, ${yellow.light[80]})`,
85
- });
86
- expect(component['status:error']).toMatchObject({
87
- '--color-border-error': red.light[60],
88
- '--color-icon-error': red.light[60],
89
- });
90
- }
91
- });
92
- });
93
-
94
- describe('butter secondary ComplexSelector', () => {
95
- it('keeps the hover fill off a disabled trigger in either form', () => {
96
- expect(generateThemeCSS(butterTheme).component).toMatch(
97
- /:hover:not\(:has\(> ?:is\(:disabled, ?\[aria-disabled="true"\]\)\)\)/,
98
- );
99
- });
100
- });
101
-
102
- describe('butter color token mapping completeness', () => {
103
- it('does not redefine the data-visualization color system', () => {
104
- expect(
105
- Object.keys(butterTheme.tokens).filter(name =>
106
- name.startsWith('--color-data-'),
107
- ),
108
- ).toEqual([]);
109
- });
110
-
111
- it('keeps every root color value concrete', () => {
112
- for (const [name, value] of Object.entries(butterTheme.tokens)) {
113
- if (!name.startsWith('--color-')) {
114
- continue;
115
- }
116
- expect(typeof value, name).toBe('string');
117
- expect(value, name).toMatch(
118
- /^(?:transparent|#[0-9a-f]{6}(?:[0-9a-f]{2})?|light-dark\(#[0-9a-f]{6}(?:[0-9a-f]{2})?, #[0-9a-f]{6}(?:[0-9a-f]{2})?\)|color-mix\(.+\)|var\(.+\))$/i,
119
- );
120
- }
121
- });
122
-
123
- it('uses no one-off color literals in the maintained theme source', () => {
124
- expect(maintainedThemeSource).not.toMatch(
125
- /#[0-9a-f]{3,8}\b|\brgba?\(|\bhsl[a]?\(|\boklch\(|\bblack\b|\bwhite\b/i,
126
- );
127
- });
128
-
129
- it('keeps maintained component text pairings at normal-text AA', () => {
130
- const {accent, neutral, red, yellow} = butterModePalettes;
131
- const pairs = [
132
- ['info status', neutral.light[15], accent.light[55]],
133
- ['error status', neutral.light[15], red.light[60]],
134
- ['neutral badge', accent.light[35], yellow.light[90]],
135
- ['light top nav', accent.light[40], neutral.light[95]],
136
- ['selected light top nav', accent.light[35], neutral.light[95]],
137
- ] as const;
138
-
139
- for (const [name, foreground, background] of pairs) {
140
- expect(contrast(foreground, background), name).toBeGreaterThanOrEqual(
141
- 4.5,
142
- );
143
- }
144
-
145
- expect(butterTheme.components?.badge).toMatchObject({
146
- 'variant:info': {
147
- backgroundColor: accent.light[55],
148
- color: neutral.light[15],
149
- },
150
- 'variant:neutral': {
151
- backgroundColor: yellow.light[90],
152
- color: accent.light[35],
153
- },
154
- 'variant:error': {
155
- backgroundColor: red.light[60],
156
- color: neutral.light[15],
157
- },
158
- });
159
- expect(butterTheme.components?.banner).toMatchObject({
160
- 'status:info': {
161
- '--color-info-muted': accent.light[55],
162
- '--color-on-info-muted': neutral.light[15],
163
- },
164
- 'status:error': {
165
- '--color-error-muted': red.light[60],
166
- '--color-on-error-muted': neutral.light[15],
167
- },
168
- });
169
- expect(
170
- butterTheme.components?.['field-status']?.['type:error'],
171
- ).toMatchObject({backgroundColor: red.light[60], color: neutral.light[15]});
172
- expect(butterTheme.components?.['top-nav-item']).toMatchObject({
173
- base: {
174
- color: `light-dark(${accent.light[40]}, ${yellow.dark[90]}cc)`,
175
- },
176
- selected: {
177
- color: `light-dark(${accent.light[35]}, ${yellow.dark[90]})`,
178
- },
179
- });
180
- });
181
- });