@discourser/design-system 0.3.1 → 0.5.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 (36) hide show
  1. package/README.md +12 -4
  2. package/dist/styles.css +5126 -0
  3. package/guidelines/Guidelines.md +92 -41
  4. package/guidelines/components/accordion.md +732 -0
  5. package/guidelines/components/avatar.md +1015 -0
  6. package/guidelines/components/badge.md +728 -0
  7. package/guidelines/components/button.md +75 -40
  8. package/guidelines/components/card.md +84 -25
  9. package/guidelines/components/checkbox.md +671 -0
  10. package/guidelines/components/dialog.md +619 -31
  11. package/guidelines/components/drawer.md +1616 -0
  12. package/guidelines/components/heading.md +576 -0
  13. package/guidelines/components/icon-button.md +92 -37
  14. package/guidelines/components/input-addon.md +685 -0
  15. package/guidelines/components/input-group.md +830 -0
  16. package/guidelines/components/input.md +92 -37
  17. package/guidelines/components/popover.md +1271 -0
  18. package/guidelines/components/progress.md +836 -0
  19. package/guidelines/components/radio-group.md +852 -0
  20. package/guidelines/components/select.md +1662 -0
  21. package/guidelines/components/skeleton.md +802 -0
  22. package/guidelines/components/slider.md +911 -0
  23. package/guidelines/components/spinner.md +783 -0
  24. package/guidelines/components/switch.md +105 -38
  25. package/guidelines/components/tabs.md +1488 -0
  26. package/guidelines/components/textarea.md +495 -0
  27. package/guidelines/components/toast.md +784 -0
  28. package/guidelines/components/tooltip.md +912 -0
  29. package/guidelines/design-tokens/colors.md +309 -72
  30. package/guidelines/design-tokens/elevation.md +615 -45
  31. package/guidelines/design-tokens/spacing.md +654 -74
  32. package/guidelines/design-tokens/typography.md +432 -50
  33. package/guidelines/overview-components.md +60 -8
  34. package/guidelines/overview-imports.md +314 -0
  35. package/guidelines/overview-patterns.md +3852 -0
  36. package/package.json +4 -2
@@ -5,6 +5,7 @@ The design system uses Material Design 3 elevation system combining surface tint
5
5
  ## What is Elevation?
6
6
 
7
7
  Elevation creates visual hierarchy by making elements appear to float above the background. M3 uses two techniques:
8
+
8
9
  1. **Surface Tints**: Background color changes (via `surfaceContainer*` tokens)
9
10
  2. **Shadows**: Subtle shadows for additional depth (optional)
10
11
 
@@ -12,14 +13,14 @@ Elevation creates visual hierarchy by making elements appear to float above the
12
13
 
13
14
  ## Elevation Levels
14
15
 
15
- | Token | Shadow Value | Usage |
16
- |-------|--------------|-------|
17
- | `level0` | none | Flat elements, no elevation |
18
- | `level1` | `0px 1px 2px rgba(0,0,0,0.3), 0px 1px 3px 1px rgba(0,0,0,0.15)` | Cards (low elevation) |
19
- | `level2` | `0px 1px 2px rgba(0,0,0,0.3), 0px 2px 6px 2px rgba(0,0,0,0.15)` | Raised cards, FAB (resting) |
20
- | `level3` | `0px 4px 8px 3px rgba(0,0,0,0.15), 0px 1px 3px rgba(0,0,0,0.3)` | Dialogs, menus |
16
+ | Token | Shadow Value | Usage |
17
+ | -------- | ---------------------------------------------------------------- | ------------------------------- |
18
+ | `level0` | none | Flat elements, no elevation |
19
+ | `level1` | `0px 1px 2px rgba(0,0,0,0.3), 0px 1px 3px 1px rgba(0,0,0,0.15)` | Cards (low elevation) |
20
+ | `level2` | `0px 1px 2px rgba(0,0,0,0.3), 0px 2px 6px 2px rgba(0,0,0,0.15)` | Raised cards, FAB (resting) |
21
+ | `level3` | `0px 4px 8px 3px rgba(0,0,0,0.15), 0px 1px 3px rgba(0,0,0,0.3)` | Dialogs, menus |
21
22
  | `level4` | `0px 6px 10px 4px rgba(0,0,0,0.15), 0px 2px 3px rgba(0,0,0,0.3)` | FAB (hover), navigation drawers |
22
- | `level5` | `0px 8px 12px 6px rgba(0,0,0,0.15), 0px 4px 4px rgba(0,0,0,0.3)` | Modals, navigation bars |
23
+ | `level5` | `0px 8px 12px 6px rgba(0,0,0,0.15), 0px 4px 4px rgba(0,0,0,0.3)` | Modals, navigation bars |
23
24
 
24
25
  ## M3 Elevation Strategy
25
26
 
@@ -54,30 +55,30 @@ Shadows can be added for additional depth, but use sparingly:
54
55
  // Card with subtle shadow
55
56
  const card = css({
56
57
  bg: 'surfaceContainerLow',
57
- boxShadow: 'level1' // Optional shadow
58
+ boxShadow: 'level1', // Optional shadow
58
59
  });
59
60
 
60
61
  // Dialog with shadow
61
62
  const dialog = css({
62
63
  bg: 'surfaceContainerHigh',
63
- boxShadow: 'level3'
64
+ boxShadow: 'level3',
64
65
  });
65
66
  ```
66
67
 
67
68
  ## Component Elevation Mapping
68
69
 
69
- | Component | Surface Container | Shadow Level | Elevation |
70
- |-----------|-------------------|--------------|-----------|
71
- | Page background | `surface` | `level0` | 0dp |
72
- | Filled Card | `surface` | `level0` | 0dp |
73
- | Outlined Card | `surface` | `level0` | 0dp |
74
- | Elevated Card | `surfaceContainerLow` | `level1` | 1dp |
75
- | Input (filled) | `surfaceContainerHighest` | `level0` | 0dp |
76
- | Button (filled) | `primary` | `level0` | 0dp |
77
- | Button (elevated) | `surfaceContainerLow` | `level1` | 1dp |
78
- | Dialog | `surfaceContainerHigh` | `level3` | 3dp |
79
- | Menu | `surfaceContainer` | `level2` | 2dp |
80
- | Navigation Drawer | `surfaceContainerLow` | `level1` | 1dp |
70
+ | Component | Surface Container | Shadow Level | Elevation |
71
+ | ----------------- | ------------------------- | ------------ | --------- |
72
+ | Page background | `surface` | `level0` | 0dp |
73
+ | Filled Card | `surface` | `level0` | 0dp |
74
+ | Outlined Card | `surface` | `level0` | 0dp |
75
+ | Elevated Card | `surfaceContainerLow` | `level1` | 1dp |
76
+ | Input (filled) | `surfaceContainerHighest` | `level0` | 0dp |
77
+ | Button (filled) | `primary` | `level0` | 0dp |
78
+ | Button (elevated) | `surfaceContainerLow` | `level1` | 1dp |
79
+ | Dialog | `surfaceContainerHigh` | `level3` | 3dp |
80
+ | Menu | `surfaceContainer` | `level2` | 2dp |
81
+ | Navigation Drawer | `surfaceContainerLow` | `level1` | 1dp |
81
82
 
82
83
  ## Usage Patterns
83
84
 
@@ -88,20 +89,20 @@ const dialog = css({
88
89
  const filledCard = css({
89
90
  bg: 'surface',
90
91
  borderColor: 'outlineVariant',
91
- borderWidth: '1px'
92
+ borderWidth: '1px',
92
93
  });
93
94
 
94
95
  // Elevated card
95
96
  const elevatedCard = css({
96
97
  bg: 'surfaceContainerLow',
97
- boxShadow: 'level1' // Optional
98
+ boxShadow: 'level1', // Optional
98
99
  });
99
100
 
100
101
  // Outlined card (no elevation)
101
102
  const outlinedCard = css({
102
103
  bg: 'surface',
103
104
  borderColor: 'outline',
104
- borderWidth: '1px'
105
+ borderWidth: '1px',
105
106
  });
106
107
  ```
107
108
 
@@ -112,19 +113,19 @@ const outlinedCard = css({
112
113
  const dialog = css({
113
114
  bg: 'surfaceContainerHigh',
114
115
  boxShadow: 'level3',
115
- borderRadius: 'large'
116
+ borderRadius: 'large',
116
117
  });
117
118
 
118
119
  // Full-screen modal
119
120
  const modal = css({
120
121
  bg: 'surfaceContainerHighest',
121
- boxShadow: 'level5'
122
+ boxShadow: 'level5',
122
123
  });
123
124
 
124
125
  // Scrim (overlay behind dialog)
125
126
  const scrim = css({
126
127
  bg: 'scrim',
127
- opacity: 0.32
128
+ opacity: 0.32,
128
129
  });
129
130
  ```
130
131
 
@@ -138,8 +139,8 @@ const button = css({
138
139
  bg: 'surfaceContainerLow',
139
140
  boxShadow: 'level1',
140
141
  _hover: {
141
- boxShadow: 'level2' // Increase shadow on hover
142
- }
142
+ boxShadow: 'level2', // Increase shadow on hover
143
+ },
143
144
  });
144
145
 
145
146
  // Card hover
@@ -148,8 +149,8 @@ const card = css({
148
149
  boxShadow: 'level1',
149
150
  transition: 'box-shadow 0.2s',
150
151
  _hover: {
151
- boxShadow: 'level2'
152
- }
152
+ boxShadow: 'level2',
153
+ },
153
154
  });
154
155
  ```
155
156
 
@@ -158,24 +159,24 @@ const card = css({
158
159
  ```typescript
159
160
  // ❌ NEVER use arbitrary shadow values
160
161
  const wrong = css({
161
- boxShadow: '0 4px 6px rgba(0,0,0,0.1)'
162
+ boxShadow: '0 4px 6px rgba(0,0,0,0.1)',
162
163
  });
163
164
 
164
165
  // ❌ NEVER use heavy shadows (old Material Design style)
165
166
  const wrong = css({
166
- boxShadow: '0 10px 40px rgba(0,0,0,0.5)'
167
+ boxShadow: '0 10px 40px rgba(0,0,0,0.5)',
167
168
  });
168
169
 
169
170
  // ❌ NEVER use elevation without surface tints
170
171
  const wrong = css({
171
- bg: '#FFFFFF', // Raw color
172
- boxShadow: 'level1'
172
+ bg: '#FFFFFF', // Raw color
173
+ boxShadow: 'level1',
173
174
  });
174
175
 
175
176
  // ✅ ALWAYS use surface containers + optional shadows
176
177
  const correct = css({
177
178
  bg: 'surfaceContainerLow',
178
- boxShadow: 'level1'
179
+ boxShadow: 'level1',
179
180
  });
180
181
  ```
181
182
 
@@ -197,26 +198,594 @@ Page Background (surface, level0)
197
198
  └─ Button in Dialog (primary, level0)
198
199
  ```
199
200
 
201
+ ## How Elevation Tokens Work With Other Tokens
202
+
203
+ Elevation tokens are rarely used alone. Here are real-world examples showing how shadows and surface tints combine with color, spacing, and typography tokens to create visual hierarchy:
204
+
205
+ ### Elevated Card with Content Hierarchy
206
+
207
+ ```typescript
208
+ import { Card } from '@discourser/design-system';
209
+ import { css } from '@discourser/design-system/styled-system/css';
210
+
211
+ <Card variant="elevated">
212
+ {/* Card automatically combines: */}
213
+ {/* bg: 'surfaceContainerLow' - Color token for elevation */}
214
+ {/* boxShadow: 'level1' - Elevation token for depth */}
215
+ {/* borderRadius: 'l3' - Border radius - 12px */}
216
+
217
+ <div className={css({
218
+ p: 'lg', // Spacing - 24px padding
219
+ display: 'flex',
220
+ flexDirection: 'column',
221
+ gap: 'md' // Spacing - 16px between sections
222
+ })}>
223
+
224
+ <div className={css({
225
+ display: 'flex',
226
+ alignItems: 'center',
227
+ gap: 'sm', // Spacing - 8px between icon and title
228
+ mb: 'sm' // Spacing - 8px bottom margin
229
+ })}>
230
+ <div className={css({
231
+ bg: 'primaryContainer', // Color - icon container
232
+ color: 'onPrimaryContainer', // Color - icon color
233
+ p: 'sm', // Spacing - 8px padding
234
+ borderRadius: 'full', // Border radius - circular
235
+ boxShadow: 'level0' // Elevation - flat (no shadow)
236
+ })}>
237
+ <StarIcon size="20px" />
238
+ </div>
239
+
240
+ <h3 className={css({
241
+ textStyle: 'titleLarge', // Typography - 22px/28px
242
+ color: 'onSurface' // Color - primary text
243
+ })}>
244
+ Featured Content
245
+ </h3>
246
+ </div>
247
+
248
+ <p className={css({
249
+ textStyle: 'bodyMedium', // Typography - 14px/20px
250
+ color: 'onSurfaceVariant', // Color - secondary text
251
+ mb: 'md' // Spacing - 16px bottom margin
252
+ })}>
253
+ This card demonstrates how elevation creates visual hierarchy when
254
+ combined with proper spacing and typography.
255
+ </p>
256
+
257
+ <div className={css({
258
+ display: 'flex',
259
+ gap: 'sm' // Spacing - 8px between buttons
260
+ })}>
261
+ <Button variant="filled">
262
+ {/* Button sits on elevated surface */}
263
+ {/* bg: 'primary' - Color */}
264
+ {/* boxShadow: 'level0' - No additional shadow needed */}
265
+ {/* px: 'lg' - Spacing (24px) */}
266
+ Learn More
267
+ </Button>
268
+ </div>
269
+ </div>
270
+ </Card>
271
+ ```
272
+
273
+ ### Dialog Over Page Content (Multi-Layer Elevation)
274
+
275
+ ```typescript
276
+ import { Dialog, Button } from '@discourser/design-system';
277
+ import { css } from '@discourser/design-system/styled-system/css';
278
+
279
+ <Dialog.Root>
280
+ {/* Layer 1: Page Background (level0) */}
281
+ <div className={css({
282
+ bg: 'surface', // Color - page background (level0)
283
+ p: 'xl' // Spacing - 32px padding
284
+ })}>
285
+ <Card variant="elevated">
286
+ {/* Layer 2: Elevated Card (level1) */}
287
+ {/* bg: 'surfaceContainerLow' - Color for level1 */}
288
+ {/* boxShadow: 'level1' - Elevation shadow */}
289
+ <div className={css({ p: 'lg' })}>
290
+ <h2 className={css({
291
+ textStyle: 'headlineMedium', // Typography - 28px/36px
292
+ color: 'onSurface' // Color - primary text
293
+ })}>
294
+ Page Content
295
+ </h2>
296
+ </div>
297
+ </Card>
298
+ </div>
299
+
300
+ {/* Layer 3: Scrim/Backdrop (over everything) */}
301
+ <Dialog.Backdrop className={css({
302
+ bg: 'scrim', // Color - black overlay
303
+ opacity: 0.32 // Semi-transparent
304
+ })} />
305
+
306
+ {/* Layer 4: Dialog (highest elevation - level3) */}
307
+ <Dialog.Content className={css({
308
+ bg: 'surfaceContainerHigh', // Color - high elevation surface
309
+ color: 'onSurface', // Color - primary text
310
+ borderRadius: 'l4', // Border radius - 28px
311
+ boxShadow: 'level3', // Elevation - dialog shadow (floats above all)
312
+ p: 'xl', // Spacing - 32px padding
313
+ maxWidth: '480px',
314
+ display: 'flex',
315
+ flexDirection: 'column',
316
+ gap: 'lg' // Spacing - 24px between sections
317
+ })}>
318
+
319
+ <Dialog.Title className={css({
320
+ textStyle: 'headlineSmall', // Typography - 24px/32px
321
+ color: 'onSurface', // Color - primary text on elevated surface
322
+ mb: 'sm' // Spacing - 8px bottom margin
323
+ })}>
324
+ Confirm Action
325
+ </Dialog.Title>
326
+
327
+ <Dialog.Description className={css({
328
+ textStyle: 'bodyMedium', // Typography - 14px/20px
329
+ color: 'onSurfaceVariant' // Color - secondary text
330
+ })}>
331
+ This dialog demonstrates the highest elevation level, floating above
332
+ the backdrop and all page content.
333
+ </Dialog.Description>
334
+
335
+ <div className={css({
336
+ display: 'flex',
337
+ gap: 'sm', // Spacing - 8px between buttons
338
+ justifyContent: 'flex-end',
339
+ mt: 'md' // Spacing - 16px top margin
340
+ })}>
341
+ <Button variant="text">
342
+ {/* No elevation change needed on elevated surface */}
343
+ {/* color: 'primary' - Color */}
344
+ Cancel
345
+ </Button>
346
+ <Button variant="filled">
347
+ {/* bg: 'primary' - Color */}
348
+ {/* boxShadow: 'level0' - No shadow (already on elevated surface) */}
349
+ Confirm
350
+ </Button>
351
+ </div>
352
+ </Dialog.Content>
353
+ </Dialog.Root>
354
+ ```
355
+
356
+ ### Interactive Elevation Changes (Hover States)
357
+
358
+ ```typescript
359
+ import { css } from '@discourser/design-system/styled-system/css';
360
+
361
+ <div className={css({
362
+ display: 'grid',
363
+ gridTemplateColumns: { base: '1fr', md: 'repeat(3, 1fr)' },
364
+ gap: 'lg', // Spacing - 24px between cards
365
+ p: 'xl' // Spacing - 32px padding
366
+ })}>
367
+ {products.map(product => (
368
+ <article key={product.id} className={css({
369
+ bg: 'surfaceContainerLow', // Color - elevated surface (level1)
370
+ borderRadius: 'l3', // Border radius - 12px
371
+ boxShadow: 'level1', // Elevation - default card shadow
372
+ p: 'lg', // Spacing - 24px padding
373
+ transition: 'box-shadow 0.2s cubic-bezier(0.4, 0, 0.2, 1)', // M3 motion
374
+ cursor: 'pointer',
375
+ _hover: {
376
+ boxShadow: 'level2' // Elevation - increase on hover
377
+ },
378
+ _active: {
379
+ boxShadow: 'level0' // Elevation - decrease on click
380
+ }
381
+ })}>
382
+
383
+ <div className={css({
384
+ bg: 'surfaceContainer', // Color - slightly higher elevation
385
+ borderRadius: 'l2', // Border radius - 8px
386
+ p: 'md', // Spacing - 16px padding
387
+ mb: 'md' // Spacing - 16px bottom margin
388
+ })}>
389
+ <img
390
+ src={product.image}
391
+ alt={product.name}
392
+ className={css({
393
+ width: '100%',
394
+ height: 'auto',
395
+ borderRadius: 'l1' // Border radius - 4px
396
+ })}
397
+ />
398
+ </div>
399
+
400
+ <h3 className={css({
401
+ textStyle: 'titleMedium', // Typography - 16px/24px
402
+ color: 'onSurface', // Color - primary text
403
+ mb: 'xs' // Spacing - 4px bottom margin
404
+ })}>
405
+ {product.name}
406
+ </h3>
407
+
408
+ <p className={css({
409
+ textStyle: 'bodySmall', // Typography - 12px/16px
410
+ color: 'onSurfaceVariant', // Color - secondary text
411
+ mb: 'md' // Spacing - 16px bottom margin
412
+ })}>
413
+ {product.description}
414
+ </p>
415
+
416
+ <div className={css({
417
+ display: 'flex',
418
+ justifyContent: 'space-between',
419
+ alignItems: 'center'
420
+ })}>
421
+ <span className={css({
422
+ textStyle: 'titleLarge', // Typography - 22px/28px
423
+ color: 'primary' // Color - brand color
424
+ })}>
425
+ ${product.price}
426
+ </span>
427
+
428
+ <Button variant="filled" size="sm">
429
+ {/* px: 'md' - Spacing (16px) */}
430
+ {/* bg: 'primary' - Color */}
431
+ {/* No additional shadow - already on elevated card */}
432
+ Add to Cart
433
+ </Button>
434
+ </div>
435
+ </article>
436
+ ))}
437
+ </div>
438
+ ```
439
+
440
+ ### Floating Action Button (FAB) with Elevation States
441
+
442
+ ```typescript
443
+ import { css } from '@discourser/design-system/styled-system/css';
444
+
445
+ <button className={css({
446
+ position: 'fixed',
447
+ bottom: 'xl', // Spacing - 32px from bottom
448
+ right: 'xl', // Spacing - 32px from right
449
+ width: '56px', // Size - standard FAB size
450
+ height: '56px', // Size - standard FAB size
451
+ bg: 'primary', // Color - primary brand color
452
+ color: 'onPrimary', // Color - white icon
453
+ borderRadius: 'l3', // Border radius - 12px (M3 style)
454
+ boxShadow: 'level2', // Elevation - FAB resting state (floats)
455
+ display: 'flex',
456
+ alignItems: 'center',
457
+ justifyContent: 'center',
458
+ transition: 'all 0.2s cubic-bezier(0.4, 0, 0.2, 1)', // M3 motion
459
+ cursor: 'pointer',
460
+ _hover: {
461
+ boxShadow: 'level4', // Elevation - increase significantly on hover
462
+ transform: 'scale(1.05)' // Slight scale increase
463
+ },
464
+ _active: {
465
+ boxShadow: 'level2', // Elevation - return to resting
466
+ transform: 'scale(0.95)' // Slight press effect
467
+ }
468
+ })}>
469
+ <AddIcon size="24px" /> {/* Icon size: 24px */}
470
+ </button>
471
+ ```
472
+
473
+ ### Menu/Dropdown with Proper Elevation
474
+
475
+ ```typescript
476
+ import { Menu } from '@discourser/design-system';
477
+ import { css } from '@discourser/design-system/styled-system/css';
478
+
479
+ <Menu.Root>
480
+ <Menu.Trigger asChild>
481
+ <Button variant="outlined">
482
+ {/* Trigger button: */}
483
+ {/* borderColor: 'outline' - Color */}
484
+ {/* px: 'lg' - Spacing (24px) */}
485
+ Options
486
+ </Button>
487
+ </Menu.Trigger>
488
+
489
+ <Menu.Content className={css({
490
+ bg: 'surfaceContainer', // Color - menu elevation (level2/3)
491
+ borderRadius: 'l2', // Border radius - 8px
492
+ boxShadow: 'level2', // Elevation - menu floats above content
493
+ p: 'xs', // Spacing - 4px padding
494
+ minWidth: '200px',
495
+ border: 'none'
496
+ })}>
497
+
498
+ <Menu.Item className={css({
499
+ px: 'md', // Spacing - 16px horizontal padding
500
+ py: 'sm', // Spacing - 8px vertical padding
501
+ borderRadius: 'l1', // Border radius - 4px
502
+ textStyle: 'bodyMedium', // Typography - 14px/20px
503
+ color: 'onSurface', // Color - primary text
504
+ display: 'flex',
505
+ alignItems: 'center',
506
+ gap: 'sm', // Spacing - 8px between icon and text
507
+ _hover: {
508
+ bg: 'surfaceContainerHighest' // Color - hover background (higher than menu)
509
+ },
510
+ _focus: {
511
+ bg: 'surfaceContainerHighest',
512
+ outline: '2px solid',
513
+ outlineColor: 'primary', // Color - focus ring
514
+ outlineOffset: '-2px'
515
+ }
516
+ })}>
517
+ <EditIcon size="18px" />
518
+ Edit
519
+ </Menu.Item>
520
+
521
+ <Menu.Item className={css({
522
+ px: 'md',
523
+ py: 'sm',
524
+ borderRadius: 'l1',
525
+ textStyle: 'bodyMedium',
526
+ color: 'onSurface',
527
+ display: 'flex',
528
+ alignItems: 'center',
529
+ gap: 'sm'
530
+ })}>
531
+ <ShareIcon size="18px" />
532
+ Share
533
+ </Menu.Item>
534
+
535
+ <Menu.Separator className={css({
536
+ my: 'xs', // Spacing - 4px vertical margin
537
+ height: '1px',
538
+ bg: 'outlineVariant' // Color - subtle divider
539
+ })} />
540
+
541
+ <Menu.Item className={css({
542
+ px: 'md',
543
+ py: 'sm',
544
+ borderRadius: 'l1',
545
+ textStyle: 'bodyMedium',
546
+ color: 'error', // Color - destructive action
547
+ display: 'flex',
548
+ alignItems: 'center',
549
+ gap: 'sm',
550
+ _hover: {
551
+ bg: 'errorContainer', // Color - error background on hover
552
+ color: 'onErrorContainer' // Color - maintain contrast
553
+ }
554
+ })}>
555
+ <DeleteIcon size="18px" />
556
+ Delete
557
+ </Menu.Item>
558
+ </Menu.Content>
559
+ </Menu.Root>
560
+ ```
561
+
562
+ ### Snackbar/Toast with Inverse Surface
563
+
564
+ ```typescript
565
+ import { css } from '@discourser/design-system/styled-system/css';
566
+
567
+ <div className={css({
568
+ position: 'fixed',
569
+ bottom: 'lg', // Spacing - 24px from bottom
570
+ left: '50%',
571
+ transform: 'translateX(-50%)',
572
+ bg: 'inverseSurface', // Color - inverse surface (dark in light mode)
573
+ color: 'inverseOnSurface', // Color - light text on dark background
574
+ boxShadow: 'level2', // Elevation - floats above content
575
+ borderRadius: 'l1', // Border radius - 4px
576
+ px: 'md', // Spacing - 16px horizontal padding
577
+ py: 'sm', // Spacing - 8px vertical padding
578
+ display: 'flex',
579
+ alignItems: 'center',
580
+ gap: 'md', // Spacing - 16px between icon and content
581
+ minWidth: '344px',
582
+ maxWidth: '672px'
583
+ })}>
584
+
585
+ <CheckCircleIcon className={css({
586
+ color: 'inversePrimary', // Color - brand color on inverse surface
587
+ flexShrink: 0
588
+ })} size="20px" />
589
+
590
+ <div className={css({ flex: 1 })}>
591
+ <p className={css({
592
+ textStyle: 'bodyMedium', // Typography - 14px/20px
593
+ color: 'inverseOnSurface' // Color - light text
594
+ })}>
595
+ Your changes have been saved successfully!
596
+ </p>
597
+ </div>
598
+
599
+ <Button variant="text" size="sm" className={css({
600
+ color: 'inversePrimary', // Color - action button on inverse
601
+ px: 'sm', // Spacing - 8px horizontal
602
+ _hover: {
603
+ bg: 'rgba(255, 255, 255, 0.08)' // Subtle hover on inverse
604
+ }
605
+ })}>
606
+ Undo
607
+ </Button>
608
+
609
+ <IconButton variant="ghost" size="sm" className={css({
610
+ color: 'inverseOnSurface', // Color - close button
611
+ _hover: {
612
+ bg: 'rgba(255, 255, 255, 0.08)'
613
+ }
614
+ })}>
615
+ <CloseIcon size="18px" />
616
+ </IconButton>
617
+ </div>
618
+ ```
619
+
620
+ ### Navigation Drawer with Scrim
621
+
622
+ ```typescript
623
+ import { css } from '@discourser/design-system/styled-system/css';
624
+
625
+ <>
626
+ {/* Scrim overlay */}
627
+ <div className={css({
628
+ position: 'fixed',
629
+ inset: 0,
630
+ bg: 'scrim', // Color - black overlay
631
+ opacity: isOpen ? 0.32 : 0,
632
+ transition: 'opacity 0.2s',
633
+ pointerEvents: isOpen ? 'auto' : 'none'
634
+ })} />
635
+
636
+ {/* Navigation drawer */}
637
+ <nav className={css({
638
+ position: 'fixed',
639
+ top: 0,
640
+ left: 0,
641
+ height: '100vh',
642
+ width: '280px',
643
+ bg: 'surfaceContainerLow', // Color - elevated drawer surface
644
+ boxShadow: 'level1', // Elevation - drawer shadow
645
+ transform: isOpen ? 'translateX(0)' : 'translateX(-100%)',
646
+ transition: 'transform 0.3s cubic-bezier(0.4, 0, 0.2, 1)', // M3 motion
647
+ p: 'md', // Spacing - 16px padding
648
+ display: 'flex',
649
+ flexDirection: 'column',
650
+ gap: 'lg' // Spacing - 24px between sections
651
+ })}>
652
+
653
+ <div className={css({
654
+ display: 'flex',
655
+ alignItems: 'center',
656
+ gap: 'md', // Spacing - 16px between logo and title
657
+ pb: 'md', // Spacing - 16px bottom padding
658
+ borderBottomWidth: '1px',
659
+ borderBottomColor: 'outlineVariant' // Color - divider
660
+ })}>
661
+ <Logo size="32px" />
662
+ <h2 className={css({
663
+ textStyle: 'titleLarge', // Typography - 22px/28px
664
+ color: 'onSurface' // Color - primary text
665
+ })}>
666
+ App Name
667
+ </h2>
668
+ </div>
669
+
670
+ <ul className={css({
671
+ display: 'flex',
672
+ flexDirection: 'column',
673
+ gap: 'xxs' // Spacing - 2px between nav items
674
+ })}>
675
+ <li>
676
+ <a className={css({
677
+ display: 'flex',
678
+ alignItems: 'center',
679
+ gap: 'md', // Spacing - 16px between icon and label
680
+ px: 'md', // Spacing - 16px horizontal padding
681
+ py: 'sm', // Spacing - 8px vertical padding
682
+ borderRadius: 'l1', // Border radius - 4px
683
+ textStyle: 'labelLarge', // Typography - 14px/20px
684
+ color: 'onSurface', // Color - text
685
+ _hover: {
686
+ bg: 'surfaceContainerHighest' // Color - hover (higher than drawer)
687
+ }
688
+ })}>
689
+ <HomeIcon size="24px" />
690
+ Home
691
+ </a>
692
+ </li>
693
+ </ul>
694
+ </nav>
695
+ </>
696
+ ```
697
+
698
+ ### Multi-Token Elevation Pattern Summary
699
+
700
+ When combining elevation with other tokens, follow these patterns:
701
+
702
+ **Elevated Surface Pattern:**
703
+
704
+ ```typescript
705
+ {
706
+ bg: 'surfaceContainer*', // Color - elevation surface
707
+ boxShadow: 'level1-3', // Elevation - subtle shadow
708
+ borderRadius: 'l1-l4', // Border radius
709
+ p: 'md-xl', // Spacing - internal padding
710
+ color: 'onSurface' // Color - text maintains contrast
711
+ }
712
+ ```
713
+
714
+ **Interactive Elevation Pattern:**
715
+
716
+ ```typescript
717
+ {
718
+ bg: 'surfaceContainerLow', // Color - base elevation
719
+ boxShadow: 'level1', // Elevation - resting state
720
+ transition: 'box-shadow 0.2s', // M3 motion timing
721
+ _hover: {
722
+ boxShadow: 'level2' // Elevation - increase on hover
723
+ },
724
+ _active: {
725
+ boxShadow: 'level0' // Elevation - decrease on press
726
+ }
727
+ }
728
+ ```
729
+
730
+ **Overlay Pattern:**
731
+
732
+ ```typescript
733
+ {
734
+ // Backdrop:
735
+ bg: 'scrim', // Color - black overlay
736
+ opacity: 0.32, // Semi-transparent
737
+
738
+ // Elevated content:
739
+ bg: 'surfaceContainerHigh', // Color - high elevation
740
+ boxShadow: 'level3-5', // Elevation - floats above backdrop
741
+ p: 'xl', // Spacing - generous padding
742
+ borderRadius: 'l3-l4' // Border radius - soft corners
743
+ }
744
+ ```
745
+
746
+ **Layering Hierarchy:**
747
+
748
+ ```typescript
749
+ // Level 0 (Page):
750
+ { bg: 'surface', boxShadow: 'level0' }
751
+
752
+ // Level 1 (Cards):
753
+ { bg: 'surfaceContainerLow', boxShadow: 'level1' }
754
+
755
+ // Level 2 (Menus):
756
+ { bg: 'surfaceContainer', boxShadow: 'level2' }
757
+
758
+ // Level 3 (Dialogs):
759
+ { bg: 'surfaceContainerHigh', boxShadow: 'level3' }
760
+
761
+ // Level 4-5 (Modals):
762
+ { bg: 'surfaceContainerHighest', boxShadow: 'level4-5' }
763
+ ```
764
+
200
765
  ## Accessibility
201
766
 
202
767
  ### Color Contrast
768
+
203
769
  Surface tint changes must maintain adequate contrast:
770
+
204
771
  - Text on elevated surfaces still uses `onSurface` or `onSurfaceVariant`
205
772
  - The design system automatically handles this
206
773
 
207
774
  ### Motion and Transitions
775
+
208
776
  When elevation changes on interaction:
209
777
 
210
778
  ```typescript
211
779
  const card = css({
212
780
  transition: 'box-shadow 0.2s cubic-bezier(0.4, 0, 0.2, 1)',
213
781
  _hover: {
214
- boxShadow: 'level2'
215
- }
782
+ boxShadow: 'level2',
783
+ },
216
784
  });
217
785
  ```
218
786
 
219
787
  Use M3 motion tokens for consistent timing:
788
+
220
789
  - `fast` (100ms) - Subtle changes
221
790
  - `normal` (200ms) - Standard transitions
222
791
  - `slow` (300ms) - Emphasized changes
@@ -224,6 +793,7 @@ Use M3 motion tokens for consistent timing:
224
793
  ## Dark Mode
225
794
 
226
795
  Elevation behaves differently in dark mode:
796
+
227
797
  - **Light mode**: Higher elevation = lighter background
228
798
  - **Dark mode**: Higher elevation = lighter background (more tint)
229
799
 
@@ -265,10 +835,10 @@ Only use manual elevation tokens when creating custom layouts outside of compone
265
835
 
266
836
  ## Common Elevation Mistakes
267
837
 
268
- | ❌ Wrong | ✅ Right | Why |
269
- |---------|---------|-----|
270
- | Dialog at level1 | Dialog at level3 | Dialogs should float above content |
271
- | Heavy `boxShadow: '0 10px 50px'` | `boxShadow: 'level1'` | M3 uses subtle shadows |
272
- | Card at level5 | Card at level1 | Cards shouldn't float too high |
273
- | `bg: '#FFF', boxShadow: 'level1'` | `bg: 'surfaceContainerLow'` | Use surface containers, not raw colors |
274
- | No elevation for dialogs | `bg: 'surfaceContainerHigh'` | Dialogs need visual separation |
838
+ | ❌ Wrong | ✅ Right | Why |
839
+ | --------------------------------- | ---------------------------- | -------------------------------------- |
840
+ | Dialog at level1 | Dialog at level3 | Dialogs should float above content |
841
+ | Heavy `boxShadow: '0 10px 50px'` | `boxShadow: 'level1'` | M3 uses subtle shadows |
842
+ | Card at level5 | Card at level1 | Cards shouldn't float too high |
843
+ | `bg: '#FFF', boxShadow: 'level1'` | `bg: 'surfaceContainerLow'` | Use surface containers, not raw colors |
844
+ | No elevation for dialogs | `bg: 'surfaceContainerHigh'` | Dialogs need visual separation |