@motion-proto/live-tokens 0.8.0 → 0.10.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 (61) hide show
  1. package/.claude/skills/live-tokens-add-component/SKILL.md +488 -0
  2. package/README.md +84 -29
  3. package/dist-plugin/index.cjs +177 -125
  4. package/dist-plugin/index.d.cts +3 -2
  5. package/dist-plugin/index.d.ts +3 -2
  6. package/dist-plugin/index.js +177 -125
  7. package/package.json +8 -2
  8. package/src/editor/component-editor/BadgeEditor.svelte +44 -42
  9. package/src/editor/component-editor/ButtonEditor.svelte +224 -0
  10. package/src/editor/component-editor/CollapsibleSectionEditor.svelte +1 -7
  11. package/src/editor/component-editor/CornerBadgeEditor.svelte +44 -34
  12. package/src/editor/component-editor/ImageLightboxEditor.svelte +58 -0
  13. package/src/editor/component-editor/InputEditor.svelte +272 -0
  14. package/src/editor/component-editor/NotificationEditor.svelte +44 -65
  15. package/src/editor/component-editor/ProgressBarEditor.svelte +71 -87
  16. package/src/editor/component-editor/SegmentedControlEditor.svelte +98 -37
  17. package/src/editor/component-editor/SideNavigationEditor.svelte +342 -0
  18. package/src/editor/component-editor/index.ts +16 -1
  19. package/src/editor/component-editor/registry.ts +138 -28
  20. package/src/editor/component-editor/scaffolding/ComponentFileManager.svelte +3 -2
  21. package/src/editor/component-editor/scaffolding/ComponentsTab.svelte +2 -2
  22. package/src/editor/component-editor/scaffolding/StateBlock.svelte +9 -10
  23. package/src/editor/component-editor/scaffolding/TokenLayout.svelte +60 -36
  24. package/src/editor/component-editor/scaffolding/VariantGroup.svelte +38 -1
  25. package/src/editor/component-editor/scaffolding/buildTypeGroupTokens.ts +1 -1
  26. package/src/editor/component-editor/scaffolding/componentSources.ts +3 -3
  27. package/src/editor/component-editor/scaffolding/defaultSections.ts +15 -10
  28. package/src/editor/component-editor/scaffolding/siblings.ts +2 -2
  29. package/src/editor/component-editor/scaffolding/types.ts +2 -1
  30. package/src/editor/core/components/componentConfigKeys.ts +14 -3
  31. package/src/editor/core/components/componentConfigService.ts +7 -6
  32. package/src/editor/core/manifests/manifestService.ts +5 -4
  33. package/src/editor/core/storage/apiBase.ts +15 -0
  34. package/src/editor/core/storage/files/versionedFileResourceClient.ts +1 -1
  35. package/src/editor/core/themes/migrations/2026-05-24-collapsiblesection-drop-active-state.ts +28 -0
  36. package/src/editor/core/themes/migrations/2026-05-24-progressbar-collapse-variants.ts +41 -0
  37. package/src/editor/core/themes/migrations/2026-05-24-promote-state-shared-tokens.ts +59 -0
  38. package/src/editor/core/themes/migrations/2026-05-24-segmentedcontrol-divider-inset.ts +29 -0
  39. package/src/editor/core/themes/migrations/2026-05-25-cornerbadge-flatten-variants.ts +46 -0
  40. package/src/editor/core/themes/migrations/index.ts +10 -0
  41. package/src/editor/core/themes/slices/components.ts +9 -0
  42. package/src/editor/core/themes/themeInit.ts +3 -2
  43. package/src/editor/core/themes/themeService.ts +3 -2
  44. package/src/editor/index.ts +10 -1
  45. package/src/editor/pages/ComponentEditorPage.svelte +53 -3
  46. package/src/editor/pages/EditorShell.svelte +53 -3
  47. package/src/editor/ui/UIEasingSelector.svelte +240 -0
  48. package/src/editor/ui/variantScales.ts +34 -0
  49. package/src/system/components/Button.svelte +34 -85
  50. package/src/system/components/CollapsibleSection.svelte +1 -48
  51. package/src/system/components/CornerBadge.svelte +72 -138
  52. package/src/system/components/Dialog.svelte +24 -4
  53. package/src/system/components/ImageLightbox.svelte +578 -0
  54. package/src/system/components/Input.svelte +387 -0
  55. package/src/system/components/ProgressBar.svelte +62 -258
  56. package/src/system/components/SectionDivider.svelte +117 -43
  57. package/src/system/components/SegmentedControl.svelte +81 -15
  58. package/src/system/components/SideNavigation.svelte +777 -0
  59. package/src/system/styles/tokens.css +43 -0
  60. package/src/system/styles/tokens.generated.css +4 -183
  61. package/src/editor/component-editor/StandardButtonsEditor.svelte +0 -190
@@ -544,6 +544,49 @@
544
544
  --duration-750: 750ms;
545
545
  --duration-1000: 1000ms;
546
546
 
547
+ /* Easings — easings.net curves. Cubic-bezier values are exact; elastic and
548
+ bounce use CSS linear() multi-stop approximations (baseline 2023). */
549
+ --ease-linear: linear;
550
+
551
+ --ease-in-sine: cubic-bezier(0.12, 0, 0.39, 0);
552
+ --ease-out-sine: cubic-bezier(0.61, 1, 0.88, 1);
553
+ --ease-in-out-sine: cubic-bezier(0.37, 0, 0.63, 1);
554
+
555
+ --ease-in-quad: cubic-bezier(0.11, 0, 0.5, 0);
556
+ --ease-out-quad: cubic-bezier(0.5, 1, 0.89, 1);
557
+ --ease-in-out-quad: cubic-bezier(0.45, 0, 0.55, 1);
558
+
559
+ --ease-in-cubic: cubic-bezier(0.32, 0, 0.67, 0);
560
+ --ease-out-cubic: cubic-bezier(0.33, 1, 0.68, 1);
561
+ --ease-in-out-cubic: cubic-bezier(0.65, 0, 0.35, 1);
562
+
563
+ --ease-in-quart: cubic-bezier(0.5, 0, 0.75, 0);
564
+ --ease-out-quart: cubic-bezier(0.25, 1, 0.5, 1);
565
+ --ease-in-out-quart: cubic-bezier(0.76, 0, 0.24, 1);
566
+
567
+ --ease-in-quint: cubic-bezier(0.64, 0, 0.78, 0);
568
+ --ease-out-quint: cubic-bezier(0.22, 1, 0.36, 1);
569
+ --ease-in-out-quint: cubic-bezier(0.83, 0, 0.17, 1);
570
+
571
+ --ease-in-expo: cubic-bezier(0.7, 0, 0.84, 0);
572
+ --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
573
+ --ease-in-out-expo: cubic-bezier(0.87, 0, 0.13, 1);
574
+
575
+ --ease-in-circ: cubic-bezier(0.55, 0, 1, 0.45);
576
+ --ease-out-circ: cubic-bezier(0, 0.55, 0.45, 1);
577
+ --ease-in-out-circ: cubic-bezier(0.85, 0, 0.15, 1);
578
+
579
+ --ease-in-back: cubic-bezier(0.36, 0, 0.66, -0.56);
580
+ --ease-out-back: cubic-bezier(0.34, 1.56, 0.64, 1);
581
+ --ease-in-out-back: cubic-bezier(0.68, -0.6, 0.32, 1.6);
582
+
583
+ --ease-in-elastic: linear(0, 0.0007 8.1%, 0.0019 12.1%, 0.0027 13.7%, 0.0046 15.7%, -0.0046 18.7%, -0.0202 22.1%, -0.0234 23.6%, -0.0224 24.9%, -0.0156 26.7%, 0.0091 29.4%, 0.0666 33.4%, 0.0848 34.9%, 0.0916 36.4%, 0.0837 38.1%, 0.0581 40.1%, -0.0204 43.7%, -0.221 51.3%, -0.2825 53.6%, -0.317 55.4%, -0.3253 57.1%, -0.3071 58.8%, -0.2554 60.9%, -0.1295 63.7%, 0.4515 73.1%, 0.7257 78.4%, 0.834 81.2%, 0.9221 84.1%, 0.9817 87.1%, 1.0144 90.4%, 1.026 94.6%, 1);
584
+ --ease-out-elastic: linear(0, 0.974 4.6%, 1.026 5.4%, 1.018 6.9%, 0.952 12.9%, 0.876 15.9%, 0.751 18.8%, 0.557 22.4%, -0.451 36.3%, -0.722 42.9%, -0.832 46.6%, -0.918 51.3%, -0.916 54.8%, -0.832 59.4%, -0.665 64.6%, 0.221 78%, 0.317 81.2%, 0.317 84.4%, 0.281 87.6%, 0.232 91.1%, 0.058 100%);
585
+ --ease-in-out-elastic: linear(0, 0.0001 7.7%, -0.0048 12.7%, -0.0064 14.6%, -0.0064 16.5%, -0.0026 18.5%, 0.0179 21.4%, 0.0617 24.1%, 0.0617 26.5%, 0.0309 29%, -0.0589 32.7%, -0.3 38.1%, -0.4307 40.6%, -0.4844 43%, -0.4844 48%, -0.4307 50.4%, -0.3 52.9%, 0.3 60.5%, 0.4307 63%, 0.4844 65.4%, 0.4844 70.4%, 0.4307 72.8%, 0.3 75.3%, 0.0589 80.7%, -0.0309 84.4%, -0.0617 86.9%, -0.0617 89.3%, -0.0179 92%, 0.0026 94.9%, 0.0064 96.8%, 0.0064 98.7%, 0.0048 100%, 1);
586
+ --ease-in-bounce: linear(0, 0.005, 0.018, 0.039, 0.069, 0.108, 0.156, 0.213, 0.281, 0.36, 0.451, 0.555, 0.674, 0.81, 0.967, 0.881, 0.838, 0.838, 0.881, 0.97, 0.952, 0.95, 0.969, 0.999, 0.984, 0.982, 0.989, 1);
587
+ --ease-out-bounce: linear(0, 0.011, 0.031, 0.018, 0.05, 0.151, 0.301, 0.5, 0.747, 0.945, 0.997, 1, 0.969, 0.954, 0.969, 0.952, 0.952, 0.969, 1, 0.984, 0.982, 0.984, 0.997, 0.984, 0.989, 1);
588
+ --ease-in-out-bounce: linear(0, 0.003, 0.009, 0.019, 0.034, 0.054, 0.078, 0.107, 0.141, 0.18, 0.226, 0.278, 0.337, 0.405, 0.483, 0.471, 0.42, 0.419, 0.46, 0.494, 0.5, 0.506, 0.54, 0.581, 0.58, 0.529, 0.517, 0.595, 0.663, 0.722, 0.774, 0.819, 0.859, 0.893, 0.922, 0.946, 0.966, 0.981, 0.991, 0.997, 1);
589
+
547
590
  /* Z-Index Layers */
548
591
  --z-base: 0;
549
592
  --z-dropdown: 100;
@@ -1,7 +1,7 @@
1
1
  /* Generated by themeFileApi from the production theme and component configs. Do not edit. */
2
2
  /* tokens.css holds developer-authored defaults; this file holds editor overrides. */
3
3
 
4
- /* Production theme: my-theme */
4
+ /* Production theme: default */
5
5
  :root:root {
6
6
  --gradient-1: linear-gradient(90deg, var(--color-brand-500) 0%, var(--color-accent-500) 100%);
7
7
  --gradient-2: linear-gradient(135deg, var(--color-brand-500) 0%, var(--color-special-500) 100%);
@@ -359,186 +359,7 @@
359
359
 
360
360
  /* Component aliases (production configs differing from defaults) */
361
361
  :root:root {
362
- /* badge (my-badge) */
363
- --badge-primary-text-font-size: var(--font-size-md);
364
- --badge-primary-text-font-weight: var(--font-weight-normal);
365
- --badge-accent-text-font-size: var(--font-size-md);
366
- --badge-accent-text-font-weight: var(--font-weight-normal);
367
- --badge-neutral-text-font-size: var(--font-size-md);
368
- --badge-neutral-text-font-weight: var(--font-weight-normal);
369
- --badge-alternate-text-font-size: var(--font-size-md);
370
- --badge-alternate-text-font-weight: var(--font-weight-normal);
371
- --badge-canvas-text-font-size: var(--font-size-md);
372
- --badge-canvas-text-font-weight: var(--font-weight-normal);
373
- --badge-special-text-font-size: var(--font-size-md);
374
- --badge-special-text-font-weight: var(--font-weight-normal);
375
- --badge-success-text-font-size: var(--font-size-md);
376
- --badge-success-text-font-weight: var(--font-weight-normal);
377
- --badge-warning-text-font-size: var(--font-size-md);
378
- --badge-warning-text-font-weight: var(--font-weight-normal);
379
- --badge-danger-text-font-size: var(--font-size-md);
380
- --badge-danger-text-font-weight: var(--font-weight-normal);
381
- --badge-info-text-font-size: var(--font-size-md);
382
- --badge-info-text-font-weight: var(--font-weight-normal);
383
- --badge-primary-padding-top: var(--space-6);
384
- --badge-accent-padding-top: var(--space-6);
385
- --badge-neutral-padding-top: var(--space-6);
386
- --badge-alternate-padding-top: var(--space-6);
387
- --badge-canvas-padding-top: var(--space-6);
388
- --badge-special-padding-top: var(--space-6);
389
- --badge-success-padding-top: var(--space-6);
390
- --badge-warning-padding-top: var(--space-6);
391
- --badge-danger-padding-top: var(--space-6);
392
- --badge-info-padding-top: var(--space-6);
393
- --badge-primary-padding-right: var(--space-10);
394
- --badge-accent-padding-right: var(--space-10);
395
- --badge-neutral-padding-right: var(--space-10);
396
- --badge-alternate-padding-right: var(--space-10);
397
- --badge-canvas-padding-right: var(--space-10);
398
- --badge-special-padding-right: var(--space-10);
399
- --badge-success-padding-right: var(--space-10);
400
- --badge-warning-padding-right: var(--space-10);
401
- --badge-danger-padding-right: var(--space-10);
402
- --badge-info-padding-right: var(--space-10);
403
- --badge-primary-padding-bottom: var(--space-6);
404
- --badge-accent-padding-bottom: var(--space-6);
405
- --badge-neutral-padding-bottom: var(--space-6);
406
- --badge-alternate-padding-bottom: var(--space-6);
407
- --badge-canvas-padding-bottom: var(--space-6);
408
- --badge-special-padding-bottom: var(--space-6);
409
- --badge-success-padding-bottom: var(--space-6);
410
- --badge-warning-padding-bottom: var(--space-6);
411
- --badge-danger-padding-bottom: var(--space-6);
412
- --badge-info-padding-bottom: var(--space-6);
413
- --badge-primary-padding-left: var(--space-10);
414
- --badge-accent-padding-left: var(--space-10);
415
- --badge-neutral-padding-left: var(--space-10);
416
- --badge-alternate-padding-left: var(--space-10);
417
- --badge-canvas-padding-left: var(--space-10);
418
- --badge-special-padding-left: var(--space-10);
419
- --badge-success-padding-left: var(--space-10);
420
- --badge-warning-padding-left: var(--space-10);
421
- --badge-danger-padding-left: var(--space-10);
422
- --badge-info-padding-left: var(--space-10);
423
-
424
- /* button (my-button) */
425
- --button-primary-text-font-size: var(--font-size-md);
426
- --button-primary-text-font-weight: var(--font-weight-semibold);
427
- --button-primary-radius: var(--radius-xl);
428
- --button-primary-hover-radius: var(--radius-xl);
429
- --button-primary-disabled-radius: var(--radius-xl);
430
- --button-secondary-text-font-size: var(--font-size-md);
431
- --button-secondary-text-font-weight: var(--font-weight-semibold);
432
- --button-secondary-radius: var(--radius-xl);
433
- --button-secondary-hover-radius: var(--radius-xl);
434
- --button-secondary-disabled-radius: var(--radius-xl);
435
- --button-outline-text-font-size: var(--font-size-md);
436
- --button-outline-text-font-weight: var(--font-weight-semibold);
437
- --button-outline-radius: var(--radius-xl);
438
- --button-outline-hover-radius: var(--radius-xl);
439
- --button-outline-disabled-radius: var(--radius-xl);
440
- --button-success-text-font-size: var(--font-size-md);
441
- --button-success-text-font-weight: var(--font-weight-semibold);
442
- --button-success-radius: var(--radius-xl);
443
- --button-success-hover-radius: var(--radius-xl);
444
- --button-success-disabled-radius: var(--radius-xl);
445
- --button-danger-text-font-size: var(--font-size-md);
446
- --button-danger-text-font-weight: var(--font-weight-semibold);
447
- --button-danger-radius: var(--radius-xl);
448
- --button-danger-hover-radius: var(--radius-xl);
449
- --button-danger-disabled-radius: var(--radius-xl);
450
- --button-warning-text-font-size: var(--font-size-md);
451
- --button-warning-text-font-weight: var(--font-weight-semibold);
452
- --button-warning-radius: var(--radius-xl);
453
- --button-warning-hover-radius: var(--radius-xl);
454
- --button-warning-disabled-radius: var(--radius-xl);
455
-
456
- /* sectiondivider (my-section-divider) */
457
- --sectiondivider-lg-padding: var(--space-4);
458
- --sectiondivider-md-padding: var(--space-4);
459
- --sectiondivider-sm-padding: var(--space-4);
460
- --sectiondivider-sm-title-font-size: var(--font-size-2xl);
461
- --sectiondivider-lg-title-font-weight: var(--font-weight-bold);
462
- --sectiondivider-md-title-font-weight: var(--font-weight-bold);
463
- --sectiondivider-sm-title-font-weight: var(--font-weight-bold);
464
- --sectiondivider-lg-title-line-height: var(--line-height-md);
465
- --sectiondivider-md-title-line-height: var(--line-height-md);
466
- --sectiondivider-sm-title-line-height: var(--line-height-md);
467
- --sectiondivider-lg-title-letter-padding: var(--letter-spacing-normal);
468
- --sectiondivider-md-title-letter-padding: var(--letter-spacing-normal);
469
- --sectiondivider-sm-title-letter-padding: var(--letter-spacing-normal);
470
- --sectiondivider-md-title-outline-width: var(--border-width-4);
471
- --sectiondivider-sm-title-outline-width: var(--border-width-4);
472
- --sectiondivider-md-title-outline-color: var(--surface-accent-lowest);
473
- --sectiondivider-lg-description: var(--text-alternate);
474
- --sectiondivider-md-description-font-size: var(--font-size-lg);
475
- --sectiondivider-sm-description-font-size: var(--font-size-5xl);
476
- --sectiondivider-lg-description-font-weight: var(--font-weight-medium);
477
- --sectiondivider-md-description-font-weight: var(--font-weight-medium);
478
- --sectiondivider-sm-description-font-weight: var(--font-weight-medium);
479
- --sectiondivider-md-radius: var(--radius-lg);
480
- --sectiondivider-sm-radius: var(--radius-lg);
481
- --sectiondivider-lg-border: transparent;
482
- --sectiondivider-md-border: transparent;
483
- --sectiondivider-sm-border: transparent;
484
- --sectiondivider-lg-border-width: var(--border-width-1);
485
- --sectiondivider-md-border-width: var(--border-width-1);
486
- --sectiondivider-sm-border-width: var(--border-width-1);
487
- --sectiondivider-sm-hairline-color: var(--border-brand-medium);
488
- --sectiondivider-lg-hairline-color: var(--border-brand-medium);
489
- --sectiondivider-md-hairline-color: var(--border-brand-medium);
490
- --sectiondivider-lg-padding-top: var(--space-8);
491
- --sectiondivider-md-padding-top: var(--space-8);
492
- --sectiondivider-sm-padding-top: var(--space-8);
493
- --sectiondivider-lg-padding-right: var(--space-4);
494
- --sectiondivider-md-padding-right: var(--space-4);
495
- --sectiondivider-sm-padding-right: var(--space-4);
496
- --sectiondivider-lg-padding-bottom: var(--space-8);
497
- --sectiondivider-md-padding-bottom: var(--space-8);
498
- --sectiondivider-sm-padding-bottom: var(--space-8);
499
- --sectiondivider-lg-padding-left: var(--space-0);
500
- --sectiondivider-md-padding-left: var(--space-0);
501
- --sectiondivider-sm-padding-left: var(--space-0);
502
- --sectiondivider-lg-description-padding-top: var(--space-0);
503
- --sectiondivider-md-description-padding-top: var(--space-0);
504
- --sectiondivider-sm-description-padding-top: var(--space-0);
505
- --sectiondivider-lg-description-padding-right: var(--space-0);
506
- --sectiondivider-md-description-padding-right: var(--space-0);
507
- --sectiondivider-sm-description-padding-right: var(--space-0);
508
- --sectiondivider-lg-description-padding-bottom: var(--space-10);
509
- --sectiondivider-md-description-padding-bottom: var(--space-10);
510
- --sectiondivider-sm-description-padding-bottom: var(--space-10);
511
- --sectiondivider-lg-description-padding-left: var(--space-0);
512
- --sectiondivider-md-description-padding-left: var(--space-0);
513
- --sectiondivider-sm-description-padding-left: var(--space-0);
514
- --sectiondivider-lg-eyebrow: var(--text-brand);
515
- --sectiondivider-lg-align: start;
516
- --sectiondivider-sm-align: start;
517
- --sectiondivider-md-align: start;
518
- --sectiondivider-lg-eyebrow-display: block;
519
- --sectiondivider-lg-description-display: flex;
520
- --sectiondivider-lg-hairline: below-description;
521
- --sectiondivider-lg-eyebrow-text-transform: none;
522
- --sectiondivider-md-description-display: none;
523
- --sectiondivider-sm-description-display: none;
524
- --sectiondivider-sm-hairline: below-label;
525
- --sectiondivider-lg-background: transparent;
526
- --sectiondivider-md-background: transparent;
527
- --sectiondivider-sm-background: transparent;
528
- --sectiondivider-md-hairline: below-label;
529
- --sectiondivider-lg-title-padding: var(--space-2);
530
- --sectiondivider-md-title-padding: var(--space-2);
531
- --sectiondivider-sm-title-padding: var(--space-2);
532
- --sectiondivider-lg-title-padding-top: var(--space-2);
533
- --sectiondivider-md-title-padding-top: var(--space-2);
534
- --sectiondivider-sm-title-padding-top: var(--space-2);
535
- --sectiondivider-lg-title-padding-right: var(--space-2);
536
- --sectiondivider-md-title-padding-right: var(--space-2);
537
- --sectiondivider-sm-title-padding-right: var(--space-2);
538
- --sectiondivider-lg-title-padding-bottom: var(--space-2);
539
- --sectiondivider-md-title-padding-bottom: var(--space-2);
540
- --sectiondivider-sm-title-padding-bottom: var(--space-2);
541
- --sectiondivider-lg-title-padding-left: var(--space-2);
542
- --sectiondivider-md-title-padding-left: var(--space-0);
543
- --sectiondivider-sm-title-padding-left: var(--space-2);
362
+ /* imagelightbox (my-image-lightbox) */
363
+ --imagelightbox-tile-border: transparent;
364
+ --imagelightbox-overlay-surface: color-mix(in srgb, var(--color-neutral-950) 76%, transparent);
544
365
  }
@@ -1,190 +0,0 @@
1
- <script module lang="ts">
2
- import { buildSiblings } from './scaffolding/siblings';
3
- import type { Token } from './scaffolding/types';
4
-
5
- export const component = 'button';
6
-
7
- const variants = ['primary', 'secondary', 'outline', 'success', 'danger', 'warning'] as const;
8
- type Variant = typeof variants[number];
9
- const stateNames = ['default', 'hover', 'disabled'] as const;
10
- type StateName = typeof stateNames[number];
11
- function statePrefix(v: Variant, s: StateName): string {
12
- return s === 'default' ? `--button-${v}` : `--button-${v}-${s}`;
13
- }
14
- // Single text slot: typography props are peer rows, not a TypeEditor fieldset.
15
- // Default carries the full font shape; hover/disabled only override text color.
16
- function variantStateTokens(v: Variant, s: StateName): Token[] {
17
- const p = statePrefix(v, s);
18
- const tokens: Token[] = [
19
- { label: 'surface color', groupKey: 'surface', variable: `${p}-surface` },
20
- { label: 'border color', groupKey: 'border', variable: `${p}-border` },
21
- { label: 'border width', canBeLinked: true, groupKey: 'border-width', variable: `${p}-border-width` },
22
- { label: 'corner radius', canBeLinked: true, groupKey: 'radius', variable: `${p}-radius` },
23
- { label: 'padding', canBeLinked: true, groupKey: 'padding', variable: `${p}-padding` },
24
- ];
25
- if (s === 'default') {
26
- tokens.push(
27
- { label: 'text color', groupKey: 'text', variable: `--button-${v}-text` },
28
- { label: 'font family', canBeLinked: true, groupKey: 'font-family', variable: `--button-${v}-text-font-family` },
29
- { label: 'font size', canBeLinked: true, groupKey: 'font-size', variable: `--button-${v}-text-font-size` },
30
- { label: 'font weight', canBeLinked: true, groupKey: 'font-weight', variable: `--button-${v}-text-font-weight` },
31
- { label: 'line height', canBeLinked: true, groupKey: 'line-height', variable: `--button-${v}-text-line-height` },
32
- { label: 'icon size', canBeLinked: true, groupKey: 'icon-size', variable: `--button-${v}-icon-size` },
33
- );
34
- } else {
35
- tokens.push({ label: 'text color', groupKey: 'text', variable: `--button-${v}-${s}-text` });
36
- }
37
- return tokens;
38
- }
39
-
40
- // Outline is the only variant that paints a surface tint on :active; the rest
41
- // express press feedback through transform/shadow only. Expose just the one
42
- // tunable property here rather than adding an active state to every variant.
43
- const outlineActiveTokens: Token[] = [
44
- { label: 'surface color', groupKey: 'surface', variable: '--button-outline-active-surface' },
45
- ];
46
-
47
- function variantStates(v: Variant): Record<string, Token[]> {
48
- const out: Record<string, Token[]> = {};
49
- out.default = variantStateTokens(v, 'default');
50
- out.hover = variantStateTokens(v, 'hover');
51
- if (v === 'outline') out.active = outlineActiveTokens;
52
- out.disabled = variantStateTokens(v, 'disabled');
53
- return out;
54
- }
55
- export const allTokens: Token[] = variants.flatMap((v) =>
56
- Object.values(variantStates(v)).flat(),
57
- );
58
-
59
- // Shape props link across every variant × state (buttons share one geometry).
60
- // Typography props link across all variants.
61
- const linkableContexts = new Map<string, string>([
62
- ...variants.flatMap((v) => stateNames.flatMap((s) => [
63
- [`${statePrefix(v, s)}-border-width`, `${v} ${s}`] as const,
64
- [`${statePrefix(v, s)}-radius`, `${v} ${s}`] as const,
65
- [`${statePrefix(v, s)}-padding`, `${v} ${s}`] as const,
66
- ])),
67
- ...variants.flatMap((v) => [
68
- [`--button-${v}-text-font-family`, v] as const,
69
- [`--button-${v}-text-font-size`, v] as const,
70
- [`--button-${v}-text-font-weight`, v] as const,
71
- [`--button-${v}-text-line-height`, v] as const,
72
- [`--button-${v}-icon-size`, v] as const,
73
- ]),
74
- ]);
75
-
76
- const variantOptions = variants.map((v) => ({ value: v, label: v.charAt(0).toUpperCase() + v.slice(1) }));
77
- </script>
78
-
79
- <script lang="ts">
80
- import Button from '../../system/components/Button.svelte';
81
- import Toggle from '../ui/Toggle.svelte';
82
- import VariantGroup from './scaffolding/VariantGroup.svelte';
83
- import ComponentEditorBase from './scaffolding/ComponentEditorBase.svelte';
84
- import { editorState, setComponentAlias } from '../core/store/editorStore';
85
- import { computeLinkedBlock, withLinkedDisabled } from './scaffolding/linkedBlock';
86
-
87
- let shimmerRef = $derived($editorState.components.button?.aliases['--button-shimmer']);
88
- let shimmerEnabled = $derived(!(shimmerRef?.kind === 'token' && shimmerRef.name === '--shimmer-off'));
89
-
90
- function handleShimmerChange(checked: boolean) {
91
- setComponentAlias('button', '--button-shimmer', { kind: 'token', name: checked ? '--shimmer-on' : '--shimmer-off' });
92
- }
93
-
94
- let linked = $derived(computeLinkedBlock(component, linkableContexts, allTokens, $editorState));
95
-
96
- let visibleVariantStates = $derived((v: Variant) => Object.fromEntries(
97
- Object.entries(variantStates(v)).map(([name, list]) => [name, withLinkedDisabled(list, linked.varSet)]),
98
- ) as Record<string, Token[]>);
99
- </script>
100
-
101
- <ComponentEditorBase {component} title="Button" description="Reusable button component with multiple variants and sizes." tokens={allTokens} {linked} variants={variantOptions}>
102
- {#each variants as v}
103
- <VariantGroup
104
- name={v}
105
- title={v.charAt(0).toUpperCase() + v.slice(1)}
106
- states={visibleVariantStates(v)}
107
- {component}
108
- columns={2}
109
- siblings={buildSiblings(variants, v, variantStates)}
110
- >
111
- {#snippet extraPropertyRows(stateName)}
112
- {#if stateName === 'hover'}
113
- <div class="property-row">
114
- <span class="property-label">hover shimmer</span>
115
- <Toggle checked={shimmerEnabled} onchange={handleShimmerChange} />
116
- </div>
117
- {/if}
118
- {/snippet}
119
- {#snippet children({ activeState })}
120
- {@const forceClass = activeState === 'hover' ? 'force-hover' : ''}
121
- {@const isDisabled = activeState === 'disabled'}
122
- <div class="size-row">
123
- <div class="size-section">
124
- <span class="size-label">size="default"</span>
125
- <div class="button-showcase-grid">
126
- <div class="button-showcase-item">
127
- <Button variant={v} disabled={isDisabled} class={forceClass}>{v.charAt(0).toUpperCase() + v.slice(1)}</Button>
128
- </div>
129
- <div class="button-showcase-item">
130
- <Button variant={v} icon="fas fa-star" iconPosition="left" disabled={isDisabled} class={forceClass}>With Icon</Button>
131
- </div>
132
- </div>
133
- </div>
134
- <div class="size-divider"></div>
135
- <div class="size-section">
136
- <span class="size-label">size="small"</span>
137
- <div class="button-showcase-grid">
138
- <div class="button-showcase-item">
139
- <Button variant={v} size="small" disabled={isDisabled} class={forceClass}>{v.charAt(0).toUpperCase() + v.slice(1)}</Button>
140
- </div>
141
- <div class="button-showcase-item">
142
- <Button variant={v} size="small" icon="fas fa-star" iconPosition="left" disabled={isDisabled} class={forceClass}>With Icon</Button>
143
- </div>
144
- </div>
145
- </div>
146
- </div>
147
- {/snippet}
148
- </VariantGroup>
149
- {/each}
150
- </ComponentEditorBase>
151
-
152
- <style>
153
- .size-row {
154
- display: flex;
155
- gap: var(--space-12);
156
- align-items: flex-start;
157
- }
158
-
159
- .size-divider {
160
- width: 1px;
161
- background: var(--ui-border-low);
162
- align-self: stretch;
163
- }
164
-
165
- .size-section {
166
- display: flex;
167
- flex-direction: column;
168
- gap: var(--space-8);
169
- }
170
-
171
- .size-label {
172
- font-size: var(--font-size-xs);
173
- font-family: var(--ui-font-mono);
174
- color: var(--ui-text-tertiary);
175
- }
176
-
177
- .button-showcase-grid {
178
- display: flex;
179
- flex-wrap: wrap;
180
- gap: var(--space-16);
181
- align-items: start;
182
- }
183
-
184
- .button-showcase-item {
185
- display: flex;
186
- flex-direction: column;
187
- gap: var(--space-8);
188
- align-items: flex-start;
189
- }
190
- </style>