@discourser/design-system 0.25.3 → 0.26.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.
Files changed (49) hide show
  1. package/README.md +76 -73
  2. package/dist/{chunk-ZPECW4N2.js → chunk-4XOWPACJ.js} +257 -105
  3. package/dist/chunk-4XOWPACJ.js.map +1 -0
  4. package/dist/{chunk-QNCZYFUJ.cjs → chunk-AZ6QU2L2.cjs} +257 -105
  5. package/dist/chunk-AZ6QU2L2.cjs.map +1 -0
  6. package/dist/{chunk-TBLDQATQ.cjs → chunk-EBDNCZF6.cjs} +94 -54
  7. package/dist/chunk-EBDNCZF6.cjs.map +1 -0
  8. package/dist/{chunk-UHSL4N44.js → chunk-MAVUSE4F.js} +94 -55
  9. package/dist/chunk-MAVUSE4F.js.map +1 -0
  10. package/dist/components/Checkbox.d.ts +1 -1
  11. package/dist/components/Icons/LeftArrowIcon.d.ts +6 -0
  12. package/dist/components/Icons/LeftArrowIcon.d.ts.map +1 -0
  13. package/dist/components/Icons/RightArrowIcon.d.ts.map +1 -1
  14. package/dist/components/Icons/index.d.ts +1 -0
  15. package/dist/components/Icons/index.d.ts.map +1 -1
  16. package/dist/components/index.cjs +79 -75
  17. package/dist/components/index.d.ts +1 -0
  18. package/dist/components/index.d.ts.map +1 -1
  19. package/dist/components/index.js +1 -1
  20. package/dist/contracts/design-language.contract.d.ts +52 -18
  21. package/dist/contracts/design-language.contract.d.ts.map +1 -1
  22. package/dist/figma-codex.json +2 -2
  23. package/dist/index.cjs +83 -79
  24. package/dist/index.js +2 -2
  25. package/dist/languages/material3.language.d.ts.map +1 -1
  26. package/dist/languages/transform.d.ts +5 -5
  27. package/dist/languages/transform.d.ts.map +1 -1
  28. package/dist/preset/index.cjs +2 -2
  29. package/dist/preset/index.js +1 -1
  30. package/docs/token-name-mapping.json +614 -42
  31. package/docs/token-name-mapping.md +117 -29
  32. package/package.json +1 -1
  33. package/src/components/Icons/LeftArrowIcon.tsx +28 -0
  34. package/src/components/Icons/RightArrowIcon.tsx +7 -2
  35. package/src/components/Icons/index.ts +1 -0
  36. package/src/components/index.ts +1 -0
  37. package/src/contracts/design-language.contract.ts +69 -20
  38. package/src/languages/material3.language.ts +249 -80
  39. package/src/languages/transform.ts +45 -48
  40. package/src/preset/__tests__/translation-token-accuracy.test.ts +13 -0
  41. package/src/stories/foundations/Colors.mdx +9 -1
  42. package/src/stories/foundations/Elevation.mdx +23 -17
  43. package/src/stories/foundations/TokenReference.stories.tsx +970 -0
  44. package/src/stories/foundations/TonalPaletteDerivation.stories.tsx +782 -0
  45. package/src/stories/foundations/Typography.mdx +125 -25
  46. package/dist/chunk-QNCZYFUJ.cjs.map +0 -1
  47. package/dist/chunk-TBLDQATQ.cjs.map +0 -1
  48. package/dist/chunk-UHSL4N44.js.map +0 -1
  49. package/dist/chunk-ZPECW4N2.js.map +0 -1
@@ -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: '"Fraunces", Georgia, serif',
204
- body: '"Poppins", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
205
- mono: '"JetBrains Mono", "Fira Code", Consolas, monospace',
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
- fontSize: '57px',
210
- lineHeight: '64px',
211
- fontWeight: '400',
212
- letterSpacing: '-0.25px',
213
- fontFamily: 'display',
214
- fontVariationSettings: "'SOFT' 0, 'WONK' 1",
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
- fontSize: '45px',
218
- lineHeight: '52px',
219
- fontWeight: '400',
220
- letterSpacing: '0px',
221
- fontFamily: 'display',
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
- fontSize: '36px',
225
- lineHeight: '44px',
226
- fontWeight: '400',
227
- letterSpacing: '0px',
228
- fontFamily: 'display',
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
- fontSize: '32px',
232
- lineHeight: '40px',
233
- fontWeight: '400',
234
- letterSpacing: '0px',
235
- fontFamily: 'display',
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
- fontSize: '28px',
239
- lineHeight: '36px',
240
- fontWeight: '400',
241
- letterSpacing: '0px',
242
- fontFamily: 'display',
243
- fontVariationSettings: "'SOFT' 0, 'WONK' 1",
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
- fontSize: '24px',
247
- lineHeight: '32px',
248
- fontWeight: '400',
249
- letterSpacing: '0px',
250
- fontFamily: 'display',
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
- fontSize: '22px',
254
- lineHeight: '28px',
255
- fontWeight: '500',
256
- letterSpacing: '0px',
257
- fontFamily: 'body',
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
- fontSize: '16px',
261
- lineHeight: '24px',
262
- fontWeight: '500',
263
- letterSpacing: '0.15px',
264
- fontFamily: 'body',
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
- fontSize: '14px',
268
- lineHeight: '20px',
269
- fontWeight: '500',
270
- letterSpacing: '0.1px',
271
- fontFamily: 'body',
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
- fontSize: '18px',
277
- lineHeight: '28px',
278
- fontWeight: '400',
279
- letterSpacing: '0.5px',
280
- fontFamily: 'body',
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
- fontSize: '14px',
284
- lineHeight: '20px',
285
- fontWeight: '400',
286
- letterSpacing: '0.25px',
287
- fontFamily: 'body',
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
- fontSize: '12px',
291
- lineHeight: '16px',
292
- fontWeight: '400',
293
- letterSpacing: '0.4px',
294
- fontFamily: 'body',
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
- fontSize: '14px',
298
- lineHeight: '20px',
299
- fontWeight: '500',
300
- letterSpacing: '0.1px',
301
- fontFamily: 'body',
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
- fontSize: '12px',
305
- lineHeight: '16px',
306
- fontWeight: '500',
307
- letterSpacing: '0.5px',
308
- fontFamily: 'body',
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
- fontSize: '11px',
312
- lineHeight: '16px',
313
- fontWeight: '500',
314
- letterSpacing: '0.5px',
315
- fontFamily: 'body',
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, style]) => [
84
- name,
85
- {
86
- value: {
87
- fontFamily: `{fonts.${style.fontFamily || 'body'}}`,
88
- fontSize: style.fontSize,
89
- lineHeight: style.lineHeight,
90
- fontWeight: style.fontWeight,
91
- letterSpacing: style.letterSpacing,
92
- ...(style.fontVariationSettings
93
- ? { fontVariationSettings: style.fontVariationSettings }
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, { fontSize: string }>) {
115
+ function extractFontSizes(scale: Record<string, TypeScaleStep>) {
119
116
  return Object.fromEntries(
120
- Object.entries(scale).map(([name, style]) => [
117
+ Object.entries(scale).map(([name, step]) => [
121
118
  name,
122
- { value: style.fontSize },
119
+ { value: step.geometry.fontSize },
123
120
  ]),
124
121
  );
125
122
  }
126
123
 
127
- function extractLineHeights(scale: Record<string, { lineHeight: string }>) {
124
+ function extractLineHeights(scale: Record<string, TypeScaleStep>) {
128
125
  return Object.fromEntries(
129
- Object.entries(scale).map(([name, style]) => [
126
+ Object.entries(scale).map(([name, step]) => [
130
127
  name,
131
- { value: style.lineHeight },
128
+ { value: step.geometry.lineHeight },
132
129
  ]),
133
130
  );
134
131
  }
135
132
 
136
- function extractFontWeights(scale: Record<string, { fontWeight: string }>) {
133
+ function extractFontWeights(scale: Record<string, TypeScaleStep>) {
137
134
  const weights = new Map<string, string>();
138
- Object.values(scale).forEach((style) => {
139
- weights.set(style.fontWeight, style.fontWeight);
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, style]) => [
147
+ Object.entries(scale).map(([name, step]) => [
151
148
  name,
152
- { value: style.letterSpacing },
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: 'primaryContainer'
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: 'sm'
31
- boxShadow: 'md'
32
-
33
- // ❌ Don't use base tokens directly
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: 'xs',
216
- borderRadius: 'medium',
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: 'large',
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
  ```