@discourser/design-system 0.25.3 → 0.27.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/README.md +76 -73
- package/dist/{chunk-ZPECW4N2.js → chunk-4XOWPACJ.js} +257 -105
- package/dist/chunk-4XOWPACJ.js.map +1 -0
- package/dist/{chunk-QNCZYFUJ.cjs → chunk-AZ6QU2L2.cjs} +257 -105
- package/dist/chunk-AZ6QU2L2.cjs.map +1 -0
- package/dist/{chunk-TBLDQATQ.cjs → chunk-EBDNCZF6.cjs} +94 -54
- package/dist/chunk-EBDNCZF6.cjs.map +1 -0
- package/dist/{chunk-UHSL4N44.js → chunk-MAVUSE4F.js} +94 -55
- package/dist/chunk-MAVUSE4F.js.map +1 -0
- package/dist/components/Checkbox.d.ts +1 -1
- package/dist/components/Icons/LeftArrowIcon.d.ts +6 -0
- package/dist/components/Icons/LeftArrowIcon.d.ts.map +1 -0
- package/dist/components/Icons/RightArrowIcon.d.ts.map +1 -1
- package/dist/components/Icons/index.d.ts +1 -0
- package/dist/components/Icons/index.d.ts.map +1 -1
- package/dist/components/index.cjs +79 -75
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +1 -1
- package/dist/contracts/design-language.contract.d.ts +52 -18
- package/dist/contracts/design-language.contract.d.ts.map +1 -1
- package/dist/figma-codex.json +2 -2
- package/dist/index.cjs +83 -79
- package/dist/index.js +2 -2
- package/dist/languages/material3.language.d.ts.map +1 -1
- package/dist/languages/transform.d.ts +5 -5
- package/dist/languages/transform.d.ts.map +1 -1
- package/dist/preset/index.cjs +2 -2
- package/dist/preset/index.js +1 -1
- package/docs/component-catalog.md +469 -0
- package/docs/superpowers/plans/2026-04-03-component-catalog-pipeline.md +667 -0
- package/docs/token-name-mapping.json +614 -42
- package/docs/token-name-mapping.md +117 -29
- package/package.json +3 -2
- package/src/components/Icons/LeftArrowIcon.tsx +28 -0
- package/src/components/Icons/RightArrowIcon.tsx +7 -2
- package/src/components/Icons/index.ts +1 -0
- package/src/components/__tests__/AbsoluteCenter.test.tsx +31 -0
- package/src/components/__tests__/Divider.test.tsx +38 -0
- package/src/components/__tests__/Group.test.tsx +34 -0
- package/src/components/__tests__/Icon.test.tsx +31 -0
- package/src/components/__tests__/SettingsPopover.test.tsx +39 -0
- package/src/components/__tests__/StudioControls.test.tsx +59 -0
- package/src/components/__tests__/Toaster.test.tsx +24 -0
- package/src/components/index.ts +1 -0
- package/src/contracts/design-language.contract.ts +69 -20
- package/src/languages/material3.language.ts +249 -80
- package/src/languages/transform.ts +45 -48
- package/src/preset/__tests__/translation-token-accuracy.test.ts +13 -0
- package/src/stories/foundations/Colors.mdx +9 -1
- package/src/stories/foundations/Elevation.mdx +23 -17
- package/src/stories/foundations/TokenReference.stories.tsx +970 -0
- package/src/stories/foundations/TonalPaletteDerivation.stories.tsx +782 -0
- package/src/stories/foundations/Typography.mdx +125 -25
- package/dist/chunk-QNCZYFUJ.cjs.map +0 -1
- package/dist/chunk-TBLDQATQ.cjs.map +0 -1
- package/dist/chunk-UHSL4N44.js.map +0 -1
- package/dist/chunk-ZPECW4N2.js.map +0 -1
- package/docs/context-share/ELEVATION_FIX_PLAN.md +0 -903
- package/docs/context-share/fix-checkbox-radio-tokens.md +0 -145
- package/docs/context-share/icon-component-prompt.md +0 -154
|
@@ -6,6 +6,10 @@ import type { DesignLanguageContract } from '../contracts/design-language.contra
|
|
|
6
6
|
* Source color: #63A002 (TastyMakers green)
|
|
7
7
|
* Generated via Material Theme Builder plugin 2024-12-24
|
|
8
8
|
*/
|
|
9
|
+
// ⚠️ After changing this file, run `pnpm figma:export` to:
|
|
10
|
+
// 1. Regenerate tokens/export-to-figma/ files for Figma import
|
|
11
|
+
// 2. Regenerate docs/token-name-mapping.json for AI agent resolution
|
|
12
|
+
// 3. Update docs/token-name-mapping.md manually to match
|
|
9
13
|
export const material3Language: DesignLanguageContract = {
|
|
10
14
|
name: 'material3',
|
|
11
15
|
version: '1.0.0',
|
|
@@ -200,119 +204,284 @@ export const material3Language: DesignLanguageContract = {
|
|
|
200
204
|
|
|
201
205
|
typography: {
|
|
202
206
|
fonts: {
|
|
203
|
-
display:
|
|
204
|
-
|
|
205
|
-
|
|
207
|
+
display: {
|
|
208
|
+
family: '"Fraunces", Georgia, serif',
|
|
209
|
+
figmaName: 'Fraunces',
|
|
210
|
+
weightMap: {
|
|
211
|
+
'100': 'Thin',
|
|
212
|
+
'300': 'Light',
|
|
213
|
+
'400': 'Regular',
|
|
214
|
+
'500': 'Medium',
|
|
215
|
+
'600': 'SemiBold',
|
|
216
|
+
'700': 'Bold',
|
|
217
|
+
},
|
|
218
|
+
},
|
|
219
|
+
body: {
|
|
220
|
+
family:
|
|
221
|
+
'"Poppins", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
|
|
222
|
+
figmaName: 'Poppins',
|
|
223
|
+
weightMap: {
|
|
224
|
+
'100': 'Thin',
|
|
225
|
+
'300': 'Light',
|
|
226
|
+
'400': 'Regular',
|
|
227
|
+
'500': 'Medium',
|
|
228
|
+
'600': 'SemiBold',
|
|
229
|
+
'700': 'Bold',
|
|
230
|
+
},
|
|
231
|
+
},
|
|
232
|
+
mono: {
|
|
233
|
+
family: '"JetBrains Mono", "Fira Code", Consolas, monospace',
|
|
234
|
+
figmaName: 'JetBrains Mono',
|
|
235
|
+
weightMap: {
|
|
236
|
+
'400': 'Regular',
|
|
237
|
+
'700': 'Bold',
|
|
238
|
+
},
|
|
239
|
+
},
|
|
206
240
|
},
|
|
207
241
|
scale: {
|
|
242
|
+
// ── Display ─────────────────────────────────────────────────────────────
|
|
243
|
+
|
|
208
244
|
displayLarge: {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
245
|
+
geometry: {
|
|
246
|
+
fontSize: '57px',
|
|
247
|
+
lineHeight: '64px',
|
|
248
|
+
letterSpacing: '-0.25px',
|
|
249
|
+
fontFamily: 'display',
|
|
250
|
+
fontVariationSettings: "'SOFT' 0, 'WONK' 1",
|
|
251
|
+
},
|
|
252
|
+
defaultWeight: 'regular',
|
|
253
|
+
weights: {
|
|
254
|
+
regular: { name: 'regular', fontWeight: '400' },
|
|
255
|
+
semiBold: { name: 'semiBold', fontWeight: '600' },
|
|
256
|
+
},
|
|
215
257
|
},
|
|
258
|
+
|
|
216
259
|
displayMedium: {
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
260
|
+
geometry: {
|
|
261
|
+
fontSize: '45px',
|
|
262
|
+
lineHeight: '52px',
|
|
263
|
+
letterSpacing: '0px',
|
|
264
|
+
fontFamily: 'display',
|
|
265
|
+
},
|
|
266
|
+
defaultWeight: 'regular',
|
|
267
|
+
weights: {
|
|
268
|
+
regular: { name: 'regular', fontWeight: '400' },
|
|
269
|
+
semiBold: { name: 'semiBold', fontWeight: '600' },
|
|
270
|
+
},
|
|
222
271
|
},
|
|
272
|
+
|
|
223
273
|
displaySmall: {
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
274
|
+
geometry: {
|
|
275
|
+
fontSize: '36px',
|
|
276
|
+
lineHeight: '44px',
|
|
277
|
+
letterSpacing: '0px',
|
|
278
|
+
fontFamily: 'display',
|
|
279
|
+
},
|
|
280
|
+
defaultWeight: 'regular',
|
|
281
|
+
weights: {
|
|
282
|
+
regular: { name: 'regular', fontWeight: '400' },
|
|
283
|
+
semiBold: { name: 'semiBold', fontWeight: '600' },
|
|
284
|
+
},
|
|
229
285
|
},
|
|
286
|
+
|
|
287
|
+
// ── Headline ────────────────────────────────────────────────────────────
|
|
288
|
+
|
|
230
289
|
headlineLarge: {
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
290
|
+
geometry: {
|
|
291
|
+
fontSize: '32px',
|
|
292
|
+
lineHeight: '40px',
|
|
293
|
+
letterSpacing: '0px',
|
|
294
|
+
fontFamily: 'display',
|
|
295
|
+
},
|
|
296
|
+
defaultWeight: 'regular',
|
|
297
|
+
weights: {
|
|
298
|
+
light: { name: 'light', fontWeight: '300' },
|
|
299
|
+
regular: { name: 'regular', fontWeight: '400' },
|
|
300
|
+
semiBold: { name: 'semiBold', fontWeight: '600' },
|
|
301
|
+
},
|
|
236
302
|
},
|
|
303
|
+
|
|
237
304
|
headlineMedium: {
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
305
|
+
geometry: {
|
|
306
|
+
fontSize: '28px',
|
|
307
|
+
lineHeight: '36px',
|
|
308
|
+
letterSpacing: '0px',
|
|
309
|
+
fontFamily: 'display',
|
|
310
|
+
fontVariationSettings: "'SOFT' 0, 'WONK' 1",
|
|
311
|
+
},
|
|
312
|
+
defaultWeight: 'regular',
|
|
313
|
+
weights: {
|
|
314
|
+
light: { name: 'light', fontWeight: '300' },
|
|
315
|
+
regular: { name: 'regular', fontWeight: '400' },
|
|
316
|
+
semiBold: { name: 'semiBold', fontWeight: '600' },
|
|
317
|
+
},
|
|
244
318
|
},
|
|
319
|
+
|
|
245
320
|
headlineSmall: {
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
321
|
+
geometry: {
|
|
322
|
+
fontSize: '24px',
|
|
323
|
+
lineHeight: '32px',
|
|
324
|
+
letterSpacing: '0px',
|
|
325
|
+
fontFamily: 'display',
|
|
326
|
+
},
|
|
327
|
+
defaultWeight: 'regular',
|
|
328
|
+
weights: {
|
|
329
|
+
light: { name: 'light', fontWeight: '300' },
|
|
330
|
+
regular: { name: 'regular', fontWeight: '400' },
|
|
331
|
+
semiBold: { name: 'semiBold', fontWeight: '600' },
|
|
332
|
+
},
|
|
251
333
|
},
|
|
334
|
+
|
|
335
|
+
// ── Title ────────────────────────────────────────────────────────────────
|
|
336
|
+
|
|
252
337
|
titleLarge: {
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
338
|
+
geometry: {
|
|
339
|
+
fontSize: '22px',
|
|
340
|
+
lineHeight: '28px',
|
|
341
|
+
letterSpacing: '0px',
|
|
342
|
+
fontFamily: 'body',
|
|
343
|
+
},
|
|
344
|
+
defaultWeight: 'medium',
|
|
345
|
+
weights: {
|
|
346
|
+
regular: { name: 'regular', fontWeight: '400' },
|
|
347
|
+
medium: { name: 'medium', fontWeight: '500' },
|
|
348
|
+
semiBold: { name: 'semiBold', fontWeight: '600' },
|
|
349
|
+
bold: { name: 'bold', fontWeight: '700' },
|
|
350
|
+
},
|
|
258
351
|
},
|
|
352
|
+
|
|
259
353
|
titleMedium: {
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
354
|
+
geometry: {
|
|
355
|
+
fontSize: '16px',
|
|
356
|
+
lineHeight: '24px',
|
|
357
|
+
letterSpacing: '0.15px',
|
|
358
|
+
fontFamily: 'body',
|
|
359
|
+
},
|
|
360
|
+
defaultWeight: 'medium',
|
|
361
|
+
weights: {
|
|
362
|
+
regular: { name: 'regular', fontWeight: '400' },
|
|
363
|
+
medium: { name: 'medium', fontWeight: '500' },
|
|
364
|
+
semiBold: { name: 'semiBold', fontWeight: '600' },
|
|
365
|
+
bold: { name: 'bold', fontWeight: '700' },
|
|
366
|
+
},
|
|
265
367
|
},
|
|
368
|
+
|
|
266
369
|
titleSmall: {
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
370
|
+
geometry: {
|
|
371
|
+
fontSize: '14px',
|
|
372
|
+
lineHeight: '20px',
|
|
373
|
+
letterSpacing: '0.1px',
|
|
374
|
+
fontFamily: 'body',
|
|
375
|
+
},
|
|
376
|
+
defaultWeight: 'medium',
|
|
377
|
+
weights: {
|
|
378
|
+
regular: { name: 'regular', fontWeight: '400' },
|
|
379
|
+
medium: { name: 'medium', fontWeight: '500' },
|
|
380
|
+
semiBold: { name: 'semiBold', fontWeight: '600' },
|
|
381
|
+
bold: { name: 'bold', fontWeight: '700' },
|
|
382
|
+
},
|
|
272
383
|
},
|
|
384
|
+
|
|
385
|
+
// ── Body ─────────────────────────────────────────────────────────────────
|
|
273
386
|
// Custom override: bodyLarge bumped to 18px/28px (was M3 default 16px/24px)
|
|
274
387
|
// Decision date: 2026-03-24
|
|
388
|
+
|
|
275
389
|
bodyLarge: {
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
390
|
+
geometry: {
|
|
391
|
+
fontSize: '18px',
|
|
392
|
+
lineHeight: '28px',
|
|
393
|
+
letterSpacing: '0.5px',
|
|
394
|
+
fontFamily: 'body',
|
|
395
|
+
},
|
|
396
|
+
defaultWeight: 'regular',
|
|
397
|
+
weights: {
|
|
398
|
+
light: { name: 'light', fontWeight: '300' },
|
|
399
|
+
regular: { name: 'regular', fontWeight: '400' },
|
|
400
|
+
medium: { name: 'medium', fontWeight: '500' },
|
|
401
|
+
semiBold: { name: 'semiBold', fontWeight: '600' },
|
|
402
|
+
},
|
|
281
403
|
},
|
|
404
|
+
|
|
282
405
|
bodyMedium: {
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
406
|
+
geometry: {
|
|
407
|
+
fontSize: '14px',
|
|
408
|
+
lineHeight: '20px',
|
|
409
|
+
letterSpacing: '0.25px',
|
|
410
|
+
fontFamily: 'body',
|
|
411
|
+
},
|
|
412
|
+
defaultWeight: 'regular',
|
|
413
|
+
weights: {
|
|
414
|
+
light: { name: 'light', fontWeight: '300' },
|
|
415
|
+
regular: { name: 'regular', fontWeight: '400' },
|
|
416
|
+
medium: { name: 'medium', fontWeight: '500' },
|
|
417
|
+
semiBold: { name: 'semiBold', fontWeight: '600' },
|
|
418
|
+
},
|
|
288
419
|
},
|
|
420
|
+
|
|
289
421
|
bodySmall: {
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
422
|
+
geometry: {
|
|
423
|
+
fontSize: '12px',
|
|
424
|
+
lineHeight: '16px',
|
|
425
|
+
letterSpacing: '0.4px',
|
|
426
|
+
fontFamily: 'body',
|
|
427
|
+
},
|
|
428
|
+
defaultWeight: 'regular',
|
|
429
|
+
weights: {
|
|
430
|
+
light: { name: 'light', fontWeight: '300' },
|
|
431
|
+
regular: { name: 'regular', fontWeight: '400' },
|
|
432
|
+
medium: { name: 'medium', fontWeight: '500' },
|
|
433
|
+
semiBold: { name: 'semiBold', fontWeight: '600' },
|
|
434
|
+
},
|
|
295
435
|
},
|
|
436
|
+
|
|
437
|
+
// ── Label ────────────────────────────────────────────────────────────────
|
|
438
|
+
|
|
296
439
|
labelLarge: {
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
440
|
+
geometry: {
|
|
441
|
+
fontSize: '14px',
|
|
442
|
+
lineHeight: '20px',
|
|
443
|
+
letterSpacing: '0.1px',
|
|
444
|
+
fontFamily: 'body',
|
|
445
|
+
},
|
|
446
|
+
defaultWeight: 'medium',
|
|
447
|
+
weights: {
|
|
448
|
+
light: { name: 'light', fontWeight: '300' },
|
|
449
|
+
medium: { name: 'medium', fontWeight: '500' },
|
|
450
|
+
semiBold: { name: 'semiBold', fontWeight: '600' },
|
|
451
|
+
bold: { name: 'bold', fontWeight: '700' },
|
|
452
|
+
},
|
|
302
453
|
},
|
|
454
|
+
|
|
303
455
|
labelMedium: {
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
456
|
+
geometry: {
|
|
457
|
+
fontSize: '12px',
|
|
458
|
+
lineHeight: '16px',
|
|
459
|
+
letterSpacing: '0.5px',
|
|
460
|
+
fontFamily: 'body',
|
|
461
|
+
},
|
|
462
|
+
defaultWeight: 'medium',
|
|
463
|
+
weights: {
|
|
464
|
+
light: { name: 'light', fontWeight: '300' },
|
|
465
|
+
medium: { name: 'medium', fontWeight: '500' },
|
|
466
|
+
semiBold: { name: 'semiBold', fontWeight: '600' },
|
|
467
|
+
bold: { name: 'bold', fontWeight: '700' },
|
|
468
|
+
},
|
|
309
469
|
},
|
|
470
|
+
|
|
310
471
|
labelSmall: {
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
472
|
+
geometry: {
|
|
473
|
+
fontSize: '11px',
|
|
474
|
+
lineHeight: '16px',
|
|
475
|
+
letterSpacing: '0.5px',
|
|
476
|
+
fontFamily: 'body',
|
|
477
|
+
},
|
|
478
|
+
defaultWeight: 'medium',
|
|
479
|
+
weights: {
|
|
480
|
+
light: { name: 'light', fontWeight: '300' },
|
|
481
|
+
medium: { name: 'medium', fontWeight: '500' },
|
|
482
|
+
semiBold: { name: 'semiBold', fontWeight: '600' },
|
|
483
|
+
bold: { name: 'bold', fontWeight: '700' },
|
|
484
|
+
},
|
|
316
485
|
},
|
|
317
486
|
},
|
|
318
487
|
},
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
DesignLanguageContract,
|
|
3
3
|
TonalPalette,
|
|
4
|
+
TypeScaleStep,
|
|
4
5
|
} from '../contracts/design-language.contract';
|
|
5
6
|
/**
|
|
6
7
|
* Transforms a DesignLanguageContract into Panda CSS theme configuration
|
|
@@ -19,33 +20,21 @@ function transformTokens(language: DesignLanguageContract) {
|
|
|
19
20
|
language.colors as unknown as Record<string, TonalPalette>,
|
|
20
21
|
),
|
|
21
22
|
fonts: {
|
|
22
|
-
display: { value: language.typography.fonts.display },
|
|
23
|
-
body: { value: language.typography.fonts.body },
|
|
24
|
-
mono: { value: language.typography.fonts.mono },
|
|
23
|
+
display: { value: language.typography.fonts.display.family },
|
|
24
|
+
body: { value: language.typography.fonts.body.family },
|
|
25
|
+
mono: { value: language.typography.fonts.mono.family },
|
|
25
26
|
},
|
|
26
27
|
fontSizes: extractFontSizes(
|
|
27
|
-
language.typography.scale as unknown as Record<
|
|
28
|
-
string,
|
|
29
|
-
{ fontSize: string }
|
|
30
|
-
>,
|
|
28
|
+
language.typography.scale as unknown as Record<string, TypeScaleStep>,
|
|
31
29
|
),
|
|
32
30
|
lineHeights: extractLineHeights(
|
|
33
|
-
language.typography.scale as unknown as Record<
|
|
34
|
-
string,
|
|
35
|
-
{ lineHeight: string }
|
|
36
|
-
>,
|
|
31
|
+
language.typography.scale as unknown as Record<string, TypeScaleStep>,
|
|
37
32
|
),
|
|
38
33
|
fontWeights: extractFontWeights(
|
|
39
|
-
language.typography.scale as unknown as Record<
|
|
40
|
-
string,
|
|
41
|
-
{ fontWeight: string }
|
|
42
|
-
>,
|
|
34
|
+
language.typography.scale as unknown as Record<string, TypeScaleStep>,
|
|
43
35
|
),
|
|
44
36
|
letterSpacings: extractLetterSpacings(
|
|
45
|
-
language.typography.scale as unknown as Record<
|
|
46
|
-
string,
|
|
47
|
-
{ letterSpacing: string }
|
|
48
|
-
>,
|
|
37
|
+
language.typography.scale as unknown as Record<string, TypeScaleStep>,
|
|
49
38
|
),
|
|
50
39
|
spacing: objectToTokens(
|
|
51
40
|
language.spacing as unknown as Record<string, string>,
|
|
@@ -77,24 +66,32 @@ function transformSemanticTokens(_language: DesignLanguageContract) {
|
|
|
77
66
|
}
|
|
78
67
|
|
|
79
68
|
function transformTextStyles(language: DesignLanguageContract) {
|
|
80
|
-
const scale = language.typography.scale
|
|
69
|
+
const scale = language.typography.scale as unknown as Record<
|
|
70
|
+
string,
|
|
71
|
+
TypeScaleStep
|
|
72
|
+
>;
|
|
81
73
|
|
|
82
74
|
return Object.fromEntries(
|
|
83
|
-
Object.entries(scale).map(([name,
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
75
|
+
Object.entries(scale).map(([name, step]) => {
|
|
76
|
+
const s = step as TypeScaleStep;
|
|
77
|
+
const defaultVariant = s.weights[s.defaultWeight];
|
|
78
|
+
const fontWeight = defaultVariant?.fontWeight ?? '400';
|
|
79
|
+
return [
|
|
80
|
+
name,
|
|
81
|
+
{
|
|
82
|
+
value: {
|
|
83
|
+
fontFamily: `{fonts.${s.geometry.fontFamily}}`,
|
|
84
|
+
fontSize: s.geometry.fontSize,
|
|
85
|
+
lineHeight: s.geometry.lineHeight,
|
|
86
|
+
fontWeight,
|
|
87
|
+
letterSpacing: s.geometry.letterSpacing,
|
|
88
|
+
...(s.geometry.fontVariationSettings
|
|
89
|
+
? { fontVariationSettings: s.geometry.fontVariationSettings }
|
|
90
|
+
: {}),
|
|
91
|
+
},
|
|
95
92
|
},
|
|
96
|
-
|
|
97
|
-
|
|
93
|
+
];
|
|
94
|
+
}),
|
|
98
95
|
);
|
|
99
96
|
}
|
|
100
97
|
|
|
@@ -115,41 +112,41 @@ function objectToTokens<T extends Record<string, string>>(obj: T) {
|
|
|
115
112
|
);
|
|
116
113
|
}
|
|
117
114
|
|
|
118
|
-
function extractFontSizes(scale: Record<string,
|
|
115
|
+
function extractFontSizes(scale: Record<string, TypeScaleStep>) {
|
|
119
116
|
return Object.fromEntries(
|
|
120
|
-
Object.entries(scale).map(([name,
|
|
117
|
+
Object.entries(scale).map(([name, step]) => [
|
|
121
118
|
name,
|
|
122
|
-
{ value:
|
|
119
|
+
{ value: step.geometry.fontSize },
|
|
123
120
|
]),
|
|
124
121
|
);
|
|
125
122
|
}
|
|
126
123
|
|
|
127
|
-
function extractLineHeights(scale: Record<string,
|
|
124
|
+
function extractLineHeights(scale: Record<string, TypeScaleStep>) {
|
|
128
125
|
return Object.fromEntries(
|
|
129
|
-
Object.entries(scale).map(([name,
|
|
126
|
+
Object.entries(scale).map(([name, step]) => [
|
|
130
127
|
name,
|
|
131
|
-
{ value:
|
|
128
|
+
{ value: step.geometry.lineHeight },
|
|
132
129
|
]),
|
|
133
130
|
);
|
|
134
131
|
}
|
|
135
132
|
|
|
136
|
-
function extractFontWeights(scale: Record<string,
|
|
133
|
+
function extractFontWeights(scale: Record<string, TypeScaleStep>) {
|
|
137
134
|
const weights = new Map<string, string>();
|
|
138
|
-
Object.values(scale).forEach((
|
|
139
|
-
|
|
135
|
+
Object.values(scale).forEach((step) => {
|
|
136
|
+
Object.values(step.weights).forEach((variant) => {
|
|
137
|
+
if (variant) weights.set(variant.fontWeight, variant.fontWeight);
|
|
138
|
+
});
|
|
140
139
|
});
|
|
141
140
|
return Object.fromEntries(
|
|
142
141
|
Array.from(weights.entries()).map(([key, value]) => [key, { value }]),
|
|
143
142
|
);
|
|
144
143
|
}
|
|
145
144
|
|
|
146
|
-
function extractLetterSpacings(
|
|
147
|
-
scale: Record<string, { letterSpacing: string }>,
|
|
148
|
-
) {
|
|
145
|
+
function extractLetterSpacings(scale: Record<string, TypeScaleStep>) {
|
|
149
146
|
return Object.fromEntries(
|
|
150
|
-
Object.entries(scale).map(([name,
|
|
147
|
+
Object.entries(scale).map(([name, step]) => [
|
|
151
148
|
name,
|
|
152
|
-
{ value:
|
|
149
|
+
{ value: step.geometry.letterSpacing },
|
|
153
150
|
]),
|
|
154
151
|
);
|
|
155
152
|
}
|
|
@@ -114,6 +114,19 @@ function buildKnownTokenList(): Set<string> {
|
|
|
114
114
|
];
|
|
115
115
|
surfaceTokens.forEach((token) => tokens.add(token));
|
|
116
116
|
|
|
117
|
+
// Add M3 role container tokens (nested dot-notation)
|
|
118
|
+
const containerTokens = [
|
|
119
|
+
'primary.container',
|
|
120
|
+
'onPrimary.container',
|
|
121
|
+
'secondary.container',
|
|
122
|
+
'onSecondary.container',
|
|
123
|
+
'tertiary.container',
|
|
124
|
+
'onTertiary.container',
|
|
125
|
+
'error.container',
|
|
126
|
+
'onError.container',
|
|
127
|
+
];
|
|
128
|
+
containerTokens.forEach((token) => tokens.add(token));
|
|
129
|
+
|
|
117
130
|
// Add common semantic tokens
|
|
118
131
|
const commonTokens = [
|
|
119
132
|
'canvas',
|
|
@@ -185,6 +185,14 @@ M3 provides 5 surface container levels for creating subtle depth without elevati
|
|
|
185
185
|
name="inversePrimary"
|
|
186
186
|
description="Primary color on inverse surface"
|
|
187
187
|
/>
|
|
188
|
+
<SemanticSwatch
|
|
189
|
+
name="inverseSecondary"
|
|
190
|
+
description="Secondary color on inverse surface (light mode = dark palette value)"
|
|
191
|
+
/>
|
|
192
|
+
<SemanticSwatch
|
|
193
|
+
name="inverseTertiary"
|
|
194
|
+
description="Tertiary color on inverse surface (light mode = dark palette value)"
|
|
195
|
+
/>
|
|
188
196
|
</div>
|
|
189
197
|
|
|
190
198
|
### Utility Colors
|
|
@@ -235,7 +243,7 @@ const buttonStyle = css({
|
|
|
235
243
|
bg: 'primary',
|
|
236
244
|
color: 'onPrimary',
|
|
237
245
|
_hover: {
|
|
238
|
-
bg: '
|
|
246
|
+
bg: 'primary.container'
|
|
239
247
|
}
|
|
240
248
|
});
|
|
241
249
|
|
|
@@ -27,13 +27,19 @@ The middle layer maps design intent to base tokens:
|
|
|
27
27
|
Components use semantic tokens for flexibility:
|
|
28
28
|
```tsx
|
|
29
29
|
// ✅ Use semantic tokens in components
|
|
30
|
-
boxShadow: '
|
|
31
|
-
boxShadow: '
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
boxShadow: 'xs' // level1 — subtle cards
|
|
31
|
+
boxShadow: 'sm' // level2 — default cards
|
|
32
|
+
boxShadow: 'md' // level3 — dialogs, dropdowns
|
|
33
|
+
boxShadow: 'lg' // level4 — drawers, sheets
|
|
34
|
+
boxShadow: 'xl' // level5 — FABs, tooltips
|
|
35
|
+
|
|
36
|
+
// ❌ Don't use base tokens directly — these are internal only
|
|
37
|
+
boxShadow: 'level1'
|
|
34
38
|
boxShadow: 'level2'
|
|
35
39
|
```
|
|
36
40
|
|
|
41
|
+
**Shadow semantic token map:** `xs`=level1, `sm`=level2, `md`=level3, `lg`=level4, `xl`=level5.
|
|
42
|
+
|
|
37
43
|
This architecture allows the design language to be swapped by changing which base tokens the semantic layer references, without touching component code.
|
|
38
44
|
|
|
39
45
|
## Elevation Scale
|
|
@@ -44,14 +50,14 @@ This architecture allows the design language to be swapped by changing which bas
|
|
|
44
50
|
|
|
45
51
|
## Elevation Reference
|
|
46
52
|
|
|
47
|
-
| Level | Shadow Value | Use Case |
|
|
48
|
-
|
|
49
|
-
| **level0** | none | Flat elements, no elevation needed |
|
|
50
|
-
| **level1** | `0px 1px 2px rgba(0,0,0,0.3), 0px 1px 3px 1px rgba(0,0,0,0.15)` | Cards at rest, contained buttons |
|
|
51
|
-
| **level2** | `0px 1px 2px rgba(0,0,0,0.3), 0px 2px 6px 2px rgba(0,0,0,0.15)` | Cards on hover, raised buttons |
|
|
52
|
-
| **level3** | `0px 4px 8px 3px rgba(0,0,0,0.15), 0px 1px 3px rgba(0,0,0,0.3)` | Dialogs, dropdowns, popovers |
|
|
53
|
-
| **level4** | `0px 6px 10px 4px rgba(0,0,0,0.15), 0px 2px 3px rgba(0,0,0,0.3)` | Navigation drawer, modal sheets |
|
|
54
|
-
| **level5** | `0px 8px 12px 6px rgba(0,0,0,0.15), 0px 4px 4px rgba(0,0,0,0.3)` | Floating action buttons, tooltips |
|
|
53
|
+
| M3 Level | Semantic Token | Shadow Value | Use Case |
|
|
54
|
+
|----------|---------------|--------------|----------|
|
|
55
|
+
| **level0** | (no shadow) | none | Flat elements, no elevation needed |
|
|
56
|
+
| **level1** | **`xs`** | `0px 1px 2px rgba(0,0,0,0.3), 0px 1px 3px 1px rgba(0,0,0,0.15)` | Cards at rest, contained buttons |
|
|
57
|
+
| **level2** | **`sm`** | `0px 1px 2px rgba(0,0,0,0.3), 0px 2px 6px 2px rgba(0,0,0,0.15)` | Cards on hover, raised buttons |
|
|
58
|
+
| **level3** | **`md`** | `0px 4px 8px 3px rgba(0,0,0,0.15), 0px 1px 3px rgba(0,0,0,0.3)` | Dialogs, dropdowns, popovers |
|
|
59
|
+
| **level4** | **`lg`** | `0px 6px 10px 4px rgba(0,0,0,0.15), 0px 2px 3px rgba(0,0,0,0.3)` | Navigation drawer, modal sheets |
|
|
60
|
+
| **level5** | **`xl`** | `0px 8px 12px 6px rgba(0,0,0,0.15), 0px 4px 4px rgba(0,0,0,0.3)` | Floating action buttons, tooltips |
|
|
55
61
|
|
|
56
62
|
---
|
|
57
63
|
|
|
@@ -212,8 +218,8 @@ Elevation works differently in dark themes:
|
|
|
212
218
|
import { css } from 'styled-system/css';
|
|
213
219
|
|
|
214
220
|
const cardStyle = css({
|
|
215
|
-
boxShadow: '
|
|
216
|
-
borderRadius: '
|
|
221
|
+
boxShadow: 'sm', // level2 — default card elevation
|
|
222
|
+
borderRadius: 'l3',
|
|
217
223
|
padding: 'lg'
|
|
218
224
|
});
|
|
219
225
|
```
|
|
@@ -246,9 +252,9 @@ const modalStyle = css({
|
|
|
246
252
|
top: '50%',
|
|
247
253
|
left: '50%',
|
|
248
254
|
transform: 'translate(-50%, -50%)',
|
|
249
|
-
boxShadow: 'md',
|
|
250
|
-
borderRadius: '
|
|
251
|
-
backgroundColor: 'surface',
|
|
255
|
+
boxShadow: 'md', // level3 — dialog elevation
|
|
256
|
+
borderRadius: 'l3',
|
|
257
|
+
backgroundColor: 'surface.container.high',
|
|
252
258
|
padding: 'xl'
|
|
253
259
|
});
|
|
254
260
|
```
|