@motion-proto/live-tokens 0.7.1 → 0.9.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 (96) hide show
  1. package/.claude/skills/live-tokens-add-component/SKILL.md +488 -0
  2. package/README.md +34 -0
  3. package/dist-plugin/index.cjs +707 -90
  4. package/dist-plugin/index.d.cts +1 -0
  5. package/dist-plugin/index.d.ts +1 -0
  6. package/dist-plugin/index.js +707 -90
  7. package/package.json +6 -2
  8. package/src/app/site.css +1 -1
  9. package/src/editor/component-editor/CollapsibleSectionEditor.svelte +34 -27
  10. package/src/editor/component-editor/DialogEditor.svelte +4 -4
  11. package/src/editor/component-editor/NotificationEditor.svelte +3 -1
  12. package/src/editor/component-editor/SectionDividerEditor.svelte +439 -112
  13. package/src/editor/component-editor/StandardButtonsEditor.svelte +13 -1
  14. package/src/editor/component-editor/editors.d.ts +10 -0
  15. package/src/editor/component-editor/index.ts +16 -1
  16. package/src/editor/component-editor/registry.ts +103 -26
  17. package/src/editor/component-editor/scaffolding/AngleDial.svelte +52 -13
  18. package/src/editor/component-editor/scaffolding/ComponentFileManager.svelte +10 -11
  19. package/src/editor/component-editor/scaffolding/ComponentsTab.svelte +2 -2
  20. package/src/editor/component-editor/scaffolding/LinkedBlock.svelte +0 -1
  21. package/src/editor/component-editor/scaffolding/RadialShapePad.svelte +483 -0
  22. package/src/editor/component-editor/scaffolding/ShadowBackdrop.svelte +15 -2
  23. package/src/editor/component-editor/scaffolding/StateBlock.svelte +103 -15
  24. package/src/editor/component-editor/scaffolding/TokenLayout.svelte +9 -6
  25. package/src/editor/component-editor/scaffolding/TypeEditor.svelte +13 -1
  26. package/src/editor/component-editor/scaffolding/VariantGroup.svelte +239 -25
  27. package/src/editor/component-editor/scaffolding/buildTypeGroupTokens.ts +1 -0
  28. package/src/editor/component-editor/scaffolding/componentSources.ts +3 -3
  29. package/src/editor/component-editor/scaffolding/defaultSections.ts +15 -10
  30. package/src/editor/component-editor/scaffolding/types.ts +11 -0
  31. package/src/editor/core/components/componentConfigKeys.ts +22 -3
  32. package/src/editor/core/components/componentConfigService.ts +2 -2
  33. package/src/editor/core/components/componentPersist.ts +7 -5
  34. package/src/editor/core/manifests/manifestService.ts +58 -3
  35. package/src/editor/core/palettes/familySwap.ts +99 -0
  36. package/src/editor/core/palettes/paletteDerivation.ts +69 -0
  37. package/src/editor/core/palettes/tokenRegistry.ts +4 -1
  38. package/src/editor/core/store/editorStore.ts +206 -12
  39. package/src/editor/core/store/editorTypes.ts +55 -12
  40. package/src/editor/core/store/gradientSource.ts +192 -0
  41. package/src/editor/core/themes/migrations/2026-05-19-collapsiblesection-drop-frame-surface.ts +28 -0
  42. package/src/editor/core/themes/migrations/2026-05-19-sectiondivider-rich-gradient.ts +35 -0
  43. package/src/editor/core/themes/migrations/2026-05-20-sectiondivider-slim-variants.ts +82 -0
  44. package/src/editor/core/themes/migrations/2026-05-21-sectiondivider-spacing-to-padding.ts +24 -0
  45. package/src/editor/core/themes/migrations/2026-05-22-sectiondivider-intrinsics-to-css.ts +81 -0
  46. package/src/editor/core/themes/migrations/index.ts +10 -0
  47. package/src/editor/core/themes/slices/components.ts +27 -4
  48. package/src/editor/core/themes/slices/gradients.ts +88 -13
  49. package/src/editor/core/themes/themeInit.ts +2 -2
  50. package/src/editor/core/themes/themeTypes.ts +56 -1
  51. package/src/editor/index.ts +10 -1
  52. package/src/editor/overlay/ColumnsOverlay.svelte +0 -1
  53. package/src/editor/overlay/LiveEditorOverlay.svelte +1 -4
  54. package/src/editor/pages/ComponentEditorPage.svelte +53 -3
  55. package/src/editor/pages/EditorShell.svelte +53 -3
  56. package/src/editor/styles/ui-editor.css +1 -0
  57. package/src/editor/styles/ui-form-controls.css +19 -20
  58. package/src/editor/ui/BezierCurveEditor.svelte +114 -63
  59. package/src/editor/ui/EditorViewSwitcher.svelte +0 -1
  60. package/src/editor/ui/FileLoadList.svelte +22 -5
  61. package/src/editor/ui/FontStackEditor.svelte +214 -76
  62. package/src/editor/ui/GradientEditor.svelte +435 -215
  63. package/src/editor/ui/GradientStopPicker.svelte +11 -3
  64. package/src/editor/ui/ManifestFileManager.svelte +71 -4
  65. package/src/editor/ui/PaletteEditor.svelte +52 -79
  66. package/src/editor/ui/ProjectFontsSection.svelte +328 -293
  67. package/src/editor/ui/ThemeFileManager.svelte +0 -4
  68. package/src/editor/ui/UIFontFamilySelector.svelte +0 -1
  69. package/src/editor/ui/UIFontSizeSelector.svelte +3 -0
  70. package/src/editor/ui/UIInfoPopover.svelte +0 -1
  71. package/src/editor/ui/UILetterSpacingSelector.svelte +65 -0
  72. package/src/editor/ui/UIPaletteSelector.svelte +31 -4
  73. package/src/editor/ui/UIPillButton.svelte +33 -3
  74. package/src/editor/ui/UISegmentedControl.svelte +114 -0
  75. package/src/editor/ui/UITokenSelector.svelte +4 -1
  76. package/src/editor/ui/VariablesTab.svelte +41 -35
  77. package/src/editor/ui/palette/OverridesPanel.svelte +14 -37
  78. package/src/editor/ui/palette/PaletteBase.svelte +3 -3
  79. package/src/editor/ui/sections/ColumnsSection.svelte +1 -2
  80. package/src/editor/ui/sections/GradientsSection.svelte +1 -1
  81. package/src/editor/ui/sections/OverlaysSection.svelte +1 -1
  82. package/src/editor/ui/sections/ShadowsSection.svelte +1 -1
  83. package/src/system/components/Button.svelte +2 -2
  84. package/src/system/components/Card.svelte +29 -1
  85. package/src/system/components/CollapsibleSection.svelte +25 -2
  86. package/src/system/components/Dialog.svelte +24 -4
  87. package/src/system/components/FloatingTokenTags.css +43 -24
  88. package/src/system/components/FloatingTokenTags.svelte +88 -137
  89. package/src/system/components/Notification.svelte +8 -1
  90. package/src/system/components/SectionDivider.svelte +532 -381
  91. package/src/system/styles/CONVENTIONS.md +1 -1
  92. package/src/system/styles/fonts.css +3 -16
  93. package/src/system/styles/tokens.css +356 -1199
  94. package/src/system/styles/tokens.generated.css +544 -0
  95. package/src/editor/component-editor/scaffolding/DividerEditor.svelte +0 -94
  96. package/src/editor/component-editor/scaffolding/GradientCard.svelte +0 -296
@@ -164,7 +164,7 @@
164
164
  .section {
165
165
  display: flex;
166
166
  flex-direction: column;
167
- gap: var(--ui-space-16);
167
+ gap: var(--ui-space-24);
168
168
  }
169
169
 
170
170
  .section-title {
@@ -244,7 +244,6 @@
244
244
  font-size: 9px;
245
245
  font-family: var(--ui-font-mono);
246
246
  color: var(--ui-text-muted);
247
- letter-spacing: 0.04em;
248
247
  pointer-events: none;
249
248
  line-height: 1;
250
249
  }
@@ -56,7 +56,7 @@
56
56
  .section {
57
57
  display: flex;
58
58
  flex-direction: column;
59
- gap: var(--ui-space-16);
59
+ gap: var(--ui-space-24);
60
60
  }
61
61
 
62
62
  .section-title {
@@ -337,7 +337,7 @@
337
337
  .section {
338
338
  display: flex;
339
339
  flex-direction: column;
340
- gap: var(--ui-space-16);
340
+ gap: var(--ui-space-24);
341
341
  }
342
342
 
343
343
  .section-title {
@@ -799,7 +799,7 @@
799
799
  .section {
800
800
  display: flex;
801
801
  flex-direction: column;
802
- gap: var(--ui-space-16);
802
+ gap: var(--ui-space-24);
803
803
  }
804
804
 
805
805
  .section-title {
@@ -140,6 +140,7 @@
140
140
  --button-outline-hover-border-width: var(--border-width-1);
141
141
  --button-outline-hover-radius: var(--radius-md);
142
142
  --button-outline-hover-padding: var(--space-8);
143
+ --button-outline-active-surface: var(--hover);
143
144
  --button-outline-disabled-surface: var(--color-transparent);
144
145
  --button-outline-disabled-text: var(--text-tertiary);
145
146
  --button-outline-disabled-border: var(--border-neutral-faint);
@@ -226,7 +227,6 @@
226
227
 
227
228
  .button {
228
229
  cursor: pointer;
229
- letter-spacing: 0.0125rem;
230
230
  display: inline-flex;
231
231
  align-items: center;
232
232
  justify-content: center;
@@ -385,7 +385,7 @@
385
385
  }
386
386
 
387
387
  &:active:not(:disabled) {
388
- background: rgba(255, 255, 255, 0.08);
388
+ background: var(--button-outline-active-surface);
389
389
  }
390
390
 
391
391
  &:disabled {
@@ -81,7 +81,6 @@
81
81
  display: flex;
82
82
  flex-direction: column;
83
83
  overflow: hidden;
84
- letter-spacing: normal;
85
84
  }
86
85
 
87
86
  .card:not(.no-hover):hover,
@@ -133,6 +132,35 @@
133
132
  @include themed-padding(--card-default-body-padding);
134
133
  }
135
134
 
135
+ /* Slot content inherits the card's body typography so consumer-side global
136
+ element rules (e.g. site.css `p { font-family: serif }`) don't override
137
+ the card-body-font-family alias. */
138
+ .card-body :global(p),
139
+ .card-body :global(ul),
140
+ .card-body :global(ol),
141
+ .card-body :global(li) {
142
+ font: inherit;
143
+ color: inherit;
144
+ }
145
+
146
+ .card-body :global(p) {
147
+ margin: 0 0 var(--space-12);
148
+ }
149
+
150
+ .card-body :global(p:last-child) {
151
+ margin-bottom: 0;
152
+ }
153
+
154
+ .card-body :global(ul),
155
+ .card-body :global(ol) {
156
+ margin: var(--space-12) 0;
157
+ padding-left: var(--space-24);
158
+ }
159
+
160
+ .card-body :global(li) {
161
+ margin-bottom: var(--space-4);
162
+ }
163
+
136
164
  .card.compact .card-body {
137
165
  font-size: var(--font-size-sm);
138
166
  }
@@ -147,7 +147,6 @@
147
147
  --collapsiblesection-divider-expanded-padding: var(--space-4);
148
148
 
149
149
  /* Container — frame (always-on outer chrome) */
150
- --collapsiblesection-container-frame-surface: var(--surface-canvas);
151
150
  --collapsiblesection-container-frame-border: var(--color-transparent);
152
151
  --collapsiblesection-container-frame-border-width: var(--border-width-3);
153
152
  --collapsiblesection-container-frame-radius: var(--radius-none);
@@ -270,7 +269,6 @@
270
269
  }
271
270
 
272
271
  .es-root.variant-container {
273
- background: var(--collapsiblesection-container-frame-surface);
274
272
  border: var(--collapsiblesection-container-frame-border-width) solid var(--collapsiblesection-container-frame-border);
275
273
  border-radius: var(--collapsiblesection-container-frame-radius);
276
274
  overflow: hidden;
@@ -286,4 +284,29 @@
286
284
  @include themed-padding(--collapsiblesection-container-expanded-padding, $h: 2);
287
285
  }
288
286
  }
287
+
288
+ .section-content {
289
+ color: var(--text-secondary);
290
+ font-size: var(--font-size-md);
291
+ line-height: var(--line-height-md);
292
+ }
293
+
294
+ /* Slot content inherits the section's body typography so consumer-side
295
+ global element rules (e.g. site.css `p { font-family: serif }`) don't
296
+ override the collapsible's intended type styling. */
297
+ .section-content :global(p),
298
+ .section-content :global(ul),
299
+ .section-content :global(ol),
300
+ .section-content :global(li) {
301
+ font: inherit;
302
+ color: inherit;
303
+ }
304
+
305
+ .section-content :global(p) {
306
+ margin: 0 0 var(--space-12);
307
+ }
308
+
309
+ .section-content :global(p:last-child) {
310
+ margin-bottom: 0;
311
+ }
289
312
  </style>
@@ -2,7 +2,6 @@
2
2
  import { createEventDispatcher, tick } from 'svelte';
3
3
  import type { Snippet } from 'svelte';
4
4
  import Button from './Button.svelte';
5
- import { editorState } from '../../editor/core/store/editorStore';
6
5
  import type { ButtonVariant, DialogButtonSpec } from './types';
7
6
 
8
7
  const BUTTON_VARIANTS: readonly ButtonVariant[] = ['primary', 'secondary', 'outline', 'success', 'danger', 'warning'];
@@ -10,6 +9,18 @@
10
9
  return v && (BUTTON_VARIANTS as readonly string[]).includes(v) ? (v as ButtonVariant) : fallback;
11
10
  }
12
11
 
12
+ // Read the configured Button variants from :root. The editor mutates these
13
+ // inline on documentElement via cssVarSync; a MutationObserver picks the
14
+ // changes up without coupling this component to the editor module graph.
15
+ // In production the var lives in the generated stylesheet and never
16
+ // changes, so the observer registers but never fires.
17
+ function readCssVar(name: string): string {
18
+ if (typeof document === 'undefined') return '';
19
+ return getComputedStyle(document.documentElement).getPropertyValue(name).trim();
20
+ }
21
+ let confirmVarValue = $state(readCssVar('--dialog-confirm-variant'));
22
+ let cancelVarValue = $state(readCssVar('--dialog-cancel-variant'));
23
+
13
24
  interface Props {
14
25
  show?: boolean;
15
26
  title?: string;
@@ -39,9 +50,8 @@
39
50
  children,
40
51
  }: Props = $props();
41
52
 
42
- let configuredConfig = $derived($editorState.components.dialog?.config ?? {});
43
- let effectiveConfirmVariant = $derived(confirm?.variant ?? asVariant(configuredConfig['--dialog-confirm-variant'] as string | undefined, 'primary'));
44
- let effectiveCancelVariant = $derived(cancel?.variant ?? asVariant(configuredConfig['--dialog-cancel-variant'] as string | undefined, 'outline'));
53
+ let effectiveConfirmVariant = $derived(confirm?.variant ?? asVariant(confirmVarValue, 'primary'));
54
+ let effectiveCancelVariant = $derived(cancel?.variant ?? asVariant(cancelVarValue, 'outline'));
45
55
 
46
56
  // Dual-fire bridge — see Button.svelte for the deprecation timeline.
47
57
  const dispatch = createEventDispatcher<{
@@ -52,6 +62,16 @@
52
62
  let cancelButtonRef: HTMLButtonElement = $state()!;
53
63
  let closeButtonRef: HTMLButtonElement = $state()!;
54
64
 
65
+ $effect(() => {
66
+ if (typeof document === 'undefined') return;
67
+ const obs = new MutationObserver(() => {
68
+ confirmVarValue = readCssVar('--dialog-confirm-variant');
69
+ cancelVarValue = readCssVar('--dialog-cancel-variant');
70
+ });
71
+ obs.observe(document.documentElement, { attributes: true, attributeFilter: ['style'] });
72
+ return () => obs.disconnect();
73
+ });
74
+
55
75
  // Focus the primary button when dialog opens (skip in inline mode so the editor doesn't steal focus).
56
76
  $effect(() => {
57
77
  if (show && !inline) {
@@ -23,7 +23,7 @@
23
23
  box-sizing: border-box;
24
24
  padding: 0.75rem 1.5rem;
25
25
  display: inline-flex;
26
- width: max-content;
26
+ width: 12rem;
27
27
  align-items: center;
28
28
  justify-content: center;
29
29
  /* Defaults; overridden inline from the active token bindings. */
@@ -46,7 +46,6 @@
46
46
  font-size: 1.25rem;
47
47
  font-weight: 700;
48
48
  color: rgba(255, 255, 255, 0.95);
49
- letter-spacing: 0.01em;
50
49
  white-space: nowrap;
51
50
  user-select: none;
52
51
  pointer-events: none;
@@ -74,11 +73,11 @@
74
73
  }
75
74
 
76
75
  .ftt-string {
77
- stroke: #9b938e;
76
+ stroke: #d4ccc6;
78
77
  stroke-width: 2;
79
78
  stroke-linecap: round;
80
79
  vector-effect: non-scaling-stroke;
81
- opacity: 0.7;
80
+ opacity: 0.5;
82
81
  transition: opacity 150ms ease, stroke 150ms ease;
83
82
  }
84
83
 
@@ -94,8 +93,8 @@
94
93
  height: 0.625rem;
95
94
  translate: -50% -50%;
96
95
  border-radius: 9999px;
97
- background: #615954;
98
- border: 1px solid #c4bcb6;
96
+ background: #c4bcb6;
97
+ border: 1px solid #f0eae4;
99
98
  pointer-events: none;
100
99
  z-index: 3;
101
100
  }
@@ -130,13 +129,7 @@
130
129
  flex-direction: column;
131
130
  align-items: center;
132
131
  gap: 0.25rem;
133
-
134
- /* Black, not page-tinted: the tinted variant produces visible banding in
135
- the soft outer halo. Composed into hover/flash filters below. */
136
- --ftt-tag-shadow:
137
- drop-shadow(0 10px 28px rgba(0, 0, 0, 0.55))
138
- drop-shadow(0 6px 60px rgba(0, 0, 0, 0.4))
139
- drop-shadow(0 0 120px rgba(0, 0, 0, 0.3));
132
+ width: 14rem;
140
133
  }
141
134
 
142
135
  /* Lift open tag so its dropdown paints over sibling tags. */
@@ -144,18 +137,35 @@
144
137
  z-index: 20;
145
138
  }
146
139
 
140
+ /* Bottom-placement chips mirror the top arc: chip first, eyebrow on the
141
+ outer (lower) side. Dropdown opens upward toward the box so the menu
142
+ doesn't fall off the stage. */
143
+ .ftt-float[data-placement="bottom"] {
144
+ flex-direction: column-reverse;
145
+ }
146
+
147
+ /* Pivot the tilt around the chip's right semicircular cap. The chip is
148
+ ~1.84rem tall so the cap center sits ~0.9rem from the chip's right edge
149
+ and ~0.9rem above its bottom — which (since the chip is the widest, last
150
+ in-flow element of the wrapper) coincides with `calc(100% - 0.9rem)` on
151
+ both axes of the wrapper. */
152
+ .ftt-float[data-pivot="right-cap"] {
153
+ transform-origin: calc(100% - 0.9rem) calc(100% - 0.9rem);
154
+ }
155
+
147
156
  @keyframes ftt-bob {
148
157
  0%, 100% { translate: -50% -50%; }
149
158
  50% { translate: -50% calc(-50% + var(--ftt-bob-distance, -8px)); }
150
159
  }
151
160
 
152
- /* --- Property label above each tag ---------------------------------------- */
161
+ /* --- Property label paired with each tag ---------------------------------- */
162
+ /* Sits on the outer side of the chip: above for top-placement chips, below
163
+ for bottom-placement chips (see `.ftt-float[data-placement="bottom"]`). */
153
164
  .ftt-float-property {
154
165
  font-family: Manrope, system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
155
166
  font-size: 0.875rem;
156
167
  font-weight: 700;
157
- text-transform: uppercase;
158
- color: #ffffffb6;
168
+ color: #ff8eeb;
159
169
  white-space: nowrap;
160
170
  }
161
171
 
@@ -178,7 +188,7 @@
178
188
  border-radius: 9999px;
179
189
  font-family: Manrope, system-ui, -apple-system, sans-serif;
180
190
  font-size: 0.875rem;
181
- font-weight: 500;
191
+ font-weight: 600;
182
192
  line-height: 1.1;
183
193
  white-space: nowrap;
184
194
  }
@@ -202,11 +212,10 @@
202
212
  margin: 0;
203
213
  cursor: grab;
204
214
  touch-action: none;
205
- filter: var(--ftt-tag-shadow);
206
215
  transition: filter 150ms ease, scale 150ms ease;
207
216
  }
208
217
  .ftt-tag-trigger:hover {
209
- filter: var(--ftt-tag-shadow) brightness(1.2);
218
+ filter: brightness(1.2);
210
219
  scale: 1.04;
211
220
  }
212
221
  .ftt-float.ftt-dragging .ftt-tag-trigger {
@@ -227,14 +236,24 @@
227
236
  }
228
237
 
229
238
  @keyframes ftt-tag-flash {
230
- 0% { scale: 1; filter: var(--ftt-tag-shadow) brightness(1) drop-shadow(0 0 0 transparent); }
231
- 25% { scale: 1.14; filter: var(--ftt-tag-shadow) brightness(1.8) drop-shadow(0 0 14px #fff5f0); }
232
- 100% { scale: 1; filter: var(--ftt-tag-shadow) brightness(1) drop-shadow(0 0 0 transparent); }
239
+ 0% { scale: 1; filter: brightness(1) drop-shadow(0 0 0 transparent); }
240
+ 25% { scale: 1.14; filter: brightness(1.8) drop-shadow(0 0 14px #fff5f0); }
241
+ 100% { scale: 1; filter: brightness(1) drop-shadow(0 0 0 transparent); }
242
+ }
243
+
244
+ /* --- Chip host ------------------------------------------------------------ */
245
+ /* Wraps the chip-trigger and (when open) the dropdown so the dropdown can
246
+ anchor directly to the chip's edges, not the float wrapper's. Without
247
+ this, `top: 100%` lands at the wrapper bottom — which is the eyebrow for
248
+ `data-placement="bottom"` — and the menu drifts off the chip. */
249
+ .ftt-chip-host {
250
+ position: relative;
251
+ display: inline-flex;
233
252
  }
234
253
 
235
254
  /* --- Dropdown menu -------------------------------------------------------- */
236
- /* Wrapper handles position/stacking only; surface lives on <MenuSelect> so
237
- menuselect-* token edits reshape the in-flight UI (this is intentional). */
255
+ /* The wrap handles position/stacking only; the surface lives on
256
+ <MenuSelect> so menuselect-* token edits reshape the in-flight UI. */
238
257
  .ftt-dropdown-wrap {
239
258
  position: absolute;
240
259
  top: calc(100% + 0.25rem);