@motion-proto/live-tokens 0.9.0 → 0.11.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 (65) hide show
  1. package/README.md +50 -29
  2. package/dist-plugin/index.cjs +177 -125
  3. package/dist-plugin/index.d.cts +3 -2
  4. package/dist-plugin/index.d.ts +3 -2
  5. package/dist-plugin/index.js +177 -125
  6. package/package.json +4 -1
  7. package/src/editor/component-editor/BadgeEditor.svelte +44 -42
  8. package/src/editor/component-editor/ButtonEditor.svelte +224 -0
  9. package/src/editor/component-editor/CardEditor.svelte +2 -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/registry.ts +35 -2
  19. package/src/editor/component-editor/scaffolding/ComponentFileManager.svelte +3 -2
  20. package/src/editor/component-editor/scaffolding/ShadowBackdrop.svelte +10 -1
  21. package/src/editor/component-editor/scaffolding/StateBlock.svelte +9 -10
  22. package/src/editor/component-editor/scaffolding/TokenLayout.svelte +60 -36
  23. package/src/editor/component-editor/scaffolding/VariantGroup.svelte +38 -1
  24. package/src/editor/component-editor/scaffolding/buildTypeGroupTokens.ts +1 -1
  25. package/src/editor/component-editor/scaffolding/siblings.ts +2 -2
  26. package/src/editor/component-editor/scaffolding/types.ts +2 -1
  27. package/src/editor/core/components/componentConfigService.ts +7 -6
  28. package/src/editor/core/manifests/manifestService.ts +5 -4
  29. package/src/editor/core/storage/apiBase.ts +15 -0
  30. package/src/editor/core/storage/files/versionedFileResourceClient.ts +1 -1
  31. package/src/editor/core/store/editorRenderer.ts +1 -4
  32. package/src/editor/core/store/editorStore.ts +5 -9
  33. package/src/editor/core/store/editorTypes.ts +6 -13
  34. package/src/editor/core/themes/migrations/2026-05-13-primary-to-brand.ts +2 -29
  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/2026-05-26-drop-overlay-extra-stops.ts +46 -0
  41. package/src/editor/core/themes/migrations/index.ts +16 -0
  42. package/src/editor/core/themes/slices/overlays.ts +44 -75
  43. package/src/editor/core/themes/themeInit.ts +3 -2
  44. package/src/editor/core/themes/themeService.ts +3 -2
  45. package/src/editor/ui/SurfacesTab.svelte +3 -7
  46. package/src/editor/ui/UIEasingSelector.svelte +240 -0
  47. package/src/editor/ui/UIPaddingSelector.svelte +2 -2
  48. package/src/editor/ui/UIPaletteSelector.svelte +151 -36
  49. package/src/editor/ui/{UIRelinkConfirmPopover.svelte → UIRelinkConfirmDialog.svelte} +107 -75
  50. package/src/editor/ui/UITokenSelector.svelte +15 -2
  51. package/src/editor/ui/sections/OverlaysSection.svelte +107 -540
  52. package/src/editor/ui/variantScales.ts +34 -0
  53. package/src/system/components/Button.svelte +34 -85
  54. package/src/system/components/Card.svelte +2 -1
  55. package/src/system/components/CollapsibleSection.svelte +1 -48
  56. package/src/system/components/CornerBadge.svelte +72 -138
  57. package/src/system/components/ImageLightbox.svelte +578 -0
  58. package/src/system/components/Input.svelte +387 -0
  59. package/src/system/components/ProgressBar.svelte +62 -258
  60. package/src/system/components/SegmentedControl.svelte +81 -15
  61. package/src/system/components/SideNavigation.svelte +777 -0
  62. package/src/system/components/TabBar.svelte +1 -1
  63. package/src/system/styles/tokens.css +48 -5
  64. package/src/system/styles/tokens.generated.css +33 -185
  65. package/src/editor/component-editor/StandardButtonsEditor.svelte +0 -190
@@ -2,22 +2,35 @@
2
2
  interface Props {
3
3
  value?: number;
4
4
  label?: string;
5
- variant?: 'primary' | 'success' | 'warning' | 'danger' | 'info';
6
- showIcon?: boolean;
5
+ /** Bar fill. Accepts either a design-system var name (`--gradient-1`,
6
+ `--color-brand-500`) or a literal CSS value (`red`, `#ff0000`,
7
+ `linear-gradient(...)`, etc.). When omitted, the themed
8
+ `--progressbar-fill` default is used. Values containing characters that
9
+ could break out of the inline style attribute or inject extra CSS rules
10
+ are dropped and the default is used instead. */
11
+ fill?: string;
7
12
  }
8
13
 
9
14
  let {
10
15
  value = 0,
11
16
  label = '',
12
- variant = 'primary',
13
- showIcon = true
17
+ fill,
14
18
  }: Props = $props();
15
19
 
16
20
  let clampedValue = $derived(Math.min(100, Math.max(0, value)));
17
- let isComplete = $derived(clampedValue >= 100);
21
+ // Inline-style injection guard: reject chars that could escape the value
22
+ // context (quotes, backslashes, newlines) or terminate the declaration to
23
+ // smuggle another property (`;`, `{`, `}`, `<`, `>`). Everything else —
24
+ // including `(`/`)` for gradient/rgb syntax — is safe inside `background:`.
25
+ let fillStyle = $derived.by(() => {
26
+ if (!fill) return '';
27
+ if (/^--[\w-]+$/.test(fill)) return `background: var(${fill});`;
28
+ if (/["'\\;{}<>\n\r]/.test(fill)) return '';
29
+ return `background: ${fill};`;
30
+ });
18
31
  </script>
19
32
 
20
- <div class="progress {variant}" class:has-label={!!label} class:has-icon={showIcon && isComplete}>
33
+ <div class="progress" class:has-label={!!label}>
21
34
  {#if label}
22
35
  <div class="progress-label">
23
36
  <span>{label}</span>
@@ -26,115 +39,38 @@
26
39
  {/if}
27
40
  <div class="progress-track">
28
41
  <div
29
- class="progress-fill {variant}"
30
- style="width: {clampedValue}%;"
42
+ class="progress-fill"
43
+ style="width: {clampedValue}%; {fillStyle}"
31
44
  ></div>
32
45
  </div>
33
- {#if showIcon && isComplete}
34
- <div class="progress-icon">
35
- <i class="fas fa-check-circle"></i>
36
- </div>
37
- {/if}
38
46
  </div>
39
47
 
40
48
  <style>
41
49
  :global(:root) {
42
- /* Primary */
43
- --progressbar-primary-track-surface: var(--surface-neutral-low);
44
- --progressbar-primary-track-border: var(--border-neutral-faint);
45
- --progressbar-primary-track-border-width: var(--border-width-1);
46
- --progressbar-primary-track-height: var(--space-8);
47
- --progressbar-primary-radius: var(--radius-full);
48
- --progressbar-primary-fill: var(--gradient-1);
49
- --progressbar-primary-label: var(--text-secondary);
50
- --progressbar-primary-label-font-family: var(--font-sans);
51
- --progressbar-primary-label-font-size: var(--font-size-sm);
52
- --progressbar-primary-label-font-weight: var(--font-weight-light);
53
- --progressbar-primary-label-line-height: var(--line-height-md);
54
- --progressbar-primary-value: var(--text-tertiary);
55
- --progressbar-primary-value-font-family: var(--font-mono);
56
- --progressbar-primary-value-font-size: var(--font-size-xs);
57
- --progressbar-primary-value-font-weight: var(--font-weight-light);
58
- --progressbar-primary-value-line-height: var(--line-height-md);
59
-
60
- /* Success */
61
- --progressbar-success-track-surface: var(--surface-neutral-low);
62
- --progressbar-success-track-border: var(--border-neutral-faint);
63
- --progressbar-success-track-border-width: var(--border-width-1);
64
- --progressbar-success-track-height: var(--space-8);
65
- --progressbar-success-radius: var(--radius-full);
66
- --progressbar-success-fill: var(--border-success);
67
- --progressbar-success-label: var(--text-secondary);
68
- --progressbar-success-label-font-family: var(--font-sans);
69
- --progressbar-success-label-font-size: var(--font-size-sm);
70
- --progressbar-success-label-font-weight: var(--font-weight-light);
71
- --progressbar-success-label-line-height: var(--line-height-md);
72
- --progressbar-success-value: var(--text-tertiary);
73
- --progressbar-success-value-font-family: var(--font-mono);
74
- --progressbar-success-value-font-size: var(--font-size-xs);
75
- --progressbar-success-value-font-weight: var(--font-weight-light);
76
- --progressbar-success-value-line-height: var(--line-height-md);
77
-
78
- /* Warning */
79
- --progressbar-warning-track-surface: var(--surface-neutral-low);
80
- --progressbar-warning-track-border: var(--border-neutral-faint);
81
- --progressbar-warning-track-border-width: var(--border-width-1);
82
- --progressbar-warning-track-height: var(--space-8);
83
- --progressbar-warning-radius: var(--radius-full);
84
- --progressbar-warning-fill: var(--border-warning);
85
- --progressbar-warning-label: var(--text-secondary);
86
- --progressbar-warning-label-font-family: var(--font-sans);
87
- --progressbar-warning-label-font-size: var(--font-size-sm);
88
- --progressbar-warning-label-font-weight: var(--font-weight-light);
89
- --progressbar-warning-label-line-height: var(--line-height-md);
90
- --progressbar-warning-value: var(--text-tertiary);
91
- --progressbar-warning-value-font-family: var(--font-mono);
92
- --progressbar-warning-value-font-size: var(--font-size-xs);
93
- --progressbar-warning-value-font-weight: var(--font-weight-light);
94
- --progressbar-warning-value-line-height: var(--line-height-md);
95
-
96
- /* Danger */
97
- --progressbar-danger-track-surface: var(--surface-neutral-low);
98
- --progressbar-danger-track-border: var(--border-neutral-faint);
99
- --progressbar-danger-track-border-width: var(--border-width-1);
100
- --progressbar-danger-track-height: var(--space-8);
101
- --progressbar-danger-radius: var(--radius-full);
102
- --progressbar-danger-fill: var(--border-danger);
103
- --progressbar-danger-label: var(--text-secondary);
104
- --progressbar-danger-label-font-family: var(--font-sans);
105
- --progressbar-danger-label-font-size: var(--font-size-sm);
106
- --progressbar-danger-label-font-weight: var(--font-weight-light);
107
- --progressbar-danger-label-line-height: var(--line-height-md);
108
- --progressbar-danger-value: var(--text-tertiary);
109
- --progressbar-danger-value-font-family: var(--font-mono);
110
- --progressbar-danger-value-font-size: var(--font-size-xs);
111
- --progressbar-danger-value-font-weight: var(--font-weight-light);
112
- --progressbar-danger-value-line-height: var(--line-height-md);
113
-
114
- /* Info */
115
- --progressbar-info-track-surface: var(--surface-neutral-low);
116
- --progressbar-info-track-border: var(--border-neutral-faint);
117
- --progressbar-info-track-border-width: var(--border-width-1);
118
- --progressbar-info-track-height: var(--space-8);
119
- --progressbar-info-radius: var(--radius-full);
120
- --progressbar-info-fill: var(--border-info);
121
- --progressbar-info-label: var(--text-secondary);
122
- --progressbar-info-label-font-family: var(--font-sans);
123
- --progressbar-info-label-font-size: var(--font-size-sm);
124
- --progressbar-info-label-font-weight: var(--font-weight-light);
125
- --progressbar-info-label-line-height: var(--line-height-md);
126
- --progressbar-info-value: var(--text-tertiary);
127
- --progressbar-info-value-font-family: var(--font-mono);
128
- --progressbar-info-value-font-size: var(--font-size-xs);
129
- --progressbar-info-value-font-weight: var(--font-weight-light);
130
- --progressbar-info-value-line-height: var(--line-height-md);
50
+ --progressbar-track-surface: var(--surface-neutral-low);
51
+ --progressbar-track-border: var(--border-neutral-faint);
52
+ --progressbar-track-border-width: var(--border-width-1);
53
+ --progressbar-track-height: var(--space-8);
54
+ --progressbar-radius: var(--radius-full);
55
+ --progressbar-fill: var(--gradient-1);
56
+ --progressbar-label-gap: var(--space-6);
57
+ --progressbar-label: var(--text-secondary);
58
+ --progressbar-label-font-family: var(--font-sans);
59
+ --progressbar-label-font-size: var(--font-size-sm);
60
+ --progressbar-label-font-weight: var(--font-weight-light);
61
+ --progressbar-label-line-height: var(--line-height-md);
62
+ --progressbar-value: var(--text-tertiary);
63
+ --progressbar-value-font-family: var(--font-mono);
64
+ --progressbar-value-font-size: var(--font-size-xs);
65
+ --progressbar-value-font-weight: var(--font-weight-light);
66
+ --progressbar-value-line-height: var(--line-height-md);
131
67
  }
132
68
 
133
69
  .progress {
134
70
  display: grid;
135
71
  grid-template-columns: minmax(0, 1fr);
136
72
  grid-template-areas: "track";
137
- row-gap: var(--space-6);
73
+ row-gap: var(--progressbar-label-gap);
138
74
  width: 100%;
139
75
  }
140
76
 
@@ -144,18 +80,6 @@
144
80
  "track";
145
81
  }
146
82
 
147
- .progress.has-icon {
148
- grid-template-columns: minmax(0, 1fr) auto;
149
- column-gap: var(--space-8);
150
- grid-template-areas: "track icon";
151
- }
152
-
153
- .progress.has-label.has-icon {
154
- grid-template-areas:
155
- "label ."
156
- "track icon";
157
- }
158
-
159
83
  .progress-label {
160
84
  grid-area: label;
161
85
  display: flex;
@@ -163,159 +87,39 @@
163
87
  align-items: center;
164
88
  }
165
89
 
90
+ .progress-label > span {
91
+ color: var(--progressbar-label);
92
+ font-family: var(--progressbar-label-font-family);
93
+ font-size: var(--progressbar-label-font-size);
94
+ font-weight: var(--progressbar-label-font-weight);
95
+ line-height: var(--progressbar-label-line-height);
96
+ }
97
+
98
+ .progress-label > .progress-value {
99
+ color: var(--progressbar-value);
100
+ font-family: var(--progressbar-value-font-family);
101
+ font-size: var(--progressbar-value-font-size);
102
+ font-weight: var(--progressbar-value-font-weight);
103
+ line-height: var(--progressbar-value-line-height);
104
+ }
105
+
166
106
  .progress-track {
167
107
  grid-area: track;
168
108
  align-self: center;
169
109
  width: 100%;
170
110
  overflow: hidden;
171
111
  border-style: solid;
112
+ background: var(--progressbar-track-surface);
113
+ border-color: var(--progressbar-track-border);
114
+ border-width: var(--progressbar-track-border-width);
115
+ border-radius: var(--progressbar-radius);
116
+ height: var(--progressbar-track-height);
172
117
  }
173
118
 
174
119
  .progress-fill {
175
120
  height: 100%;
121
+ background: var(--progressbar-fill);
122
+ border-radius: var(--progressbar-radius);
176
123
  transition: width 0.4s ease;
177
124
  }
178
-
179
- /* Primary */
180
- .progress.primary .progress-label > span {
181
- color: var(--progressbar-primary-label);
182
- font-family: var(--progressbar-primary-label-font-family);
183
- font-size: var(--progressbar-primary-label-font-size);
184
- font-weight: var(--progressbar-primary-label-font-weight);
185
- line-height: var(--progressbar-primary-label-line-height);
186
- }
187
- .progress.primary .progress-value {
188
- color: var(--progressbar-primary-value);
189
- font-family: var(--progressbar-primary-value-font-family);
190
- font-size: var(--progressbar-primary-value-font-size);
191
- font-weight: var(--progressbar-primary-value-font-weight);
192
- line-height: var(--progressbar-primary-value-line-height);
193
- }
194
- .progress.primary .progress-track {
195
- background: var(--progressbar-primary-track-surface);
196
- border-color: var(--progressbar-primary-track-border);
197
- border-width: var(--progressbar-primary-track-border-width);
198
- border-radius: var(--progressbar-primary-radius);
199
- height: var(--progressbar-primary-track-height);
200
- }
201
- .progress-fill.primary {
202
- background: var(--progressbar-primary-fill);
203
- border-radius: var(--progressbar-primary-radius);
204
- }
205
-
206
- /* Success */
207
- .progress.success .progress-label > span {
208
- color: var(--progressbar-success-label);
209
- font-family: var(--progressbar-success-label-font-family);
210
- font-size: var(--progressbar-success-label-font-size);
211
- font-weight: var(--progressbar-success-label-font-weight);
212
- line-height: var(--progressbar-success-label-line-height);
213
- }
214
- .progress.success .progress-value {
215
- color: var(--progressbar-success-value);
216
- font-family: var(--progressbar-success-value-font-family);
217
- font-size: var(--progressbar-success-value-font-size);
218
- font-weight: var(--progressbar-success-value-font-weight);
219
- line-height: var(--progressbar-success-value-line-height);
220
- }
221
- .progress.success .progress-track {
222
- background: var(--progressbar-success-track-surface);
223
- border-color: var(--progressbar-success-track-border);
224
- border-width: var(--progressbar-success-track-border-width);
225
- border-radius: var(--progressbar-success-radius);
226
- height: var(--progressbar-success-track-height);
227
- }
228
- .progress-fill.success {
229
- background: var(--progressbar-success-fill);
230
- border-radius: var(--progressbar-success-radius);
231
- }
232
-
233
- /* Warning */
234
- .progress.warning .progress-label > span {
235
- color: var(--progressbar-warning-label);
236
- font-family: var(--progressbar-warning-label-font-family);
237
- font-size: var(--progressbar-warning-label-font-size);
238
- font-weight: var(--progressbar-warning-label-font-weight);
239
- line-height: var(--progressbar-warning-label-line-height);
240
- }
241
- .progress.warning .progress-value {
242
- color: var(--progressbar-warning-value);
243
- font-family: var(--progressbar-warning-value-font-family);
244
- font-size: var(--progressbar-warning-value-font-size);
245
- font-weight: var(--progressbar-warning-value-font-weight);
246
- line-height: var(--progressbar-warning-value-line-height);
247
- }
248
- .progress.warning .progress-track {
249
- background: var(--progressbar-warning-track-surface);
250
- border-color: var(--progressbar-warning-track-border);
251
- border-width: var(--progressbar-warning-track-border-width);
252
- border-radius: var(--progressbar-warning-radius);
253
- height: var(--progressbar-warning-track-height);
254
- }
255
- .progress-fill.warning {
256
- background: var(--progressbar-warning-fill);
257
- border-radius: var(--progressbar-warning-radius);
258
- }
259
-
260
- /* Danger */
261
- .progress.danger .progress-label > span {
262
- color: var(--progressbar-danger-label);
263
- font-family: var(--progressbar-danger-label-font-family);
264
- font-size: var(--progressbar-danger-label-font-size);
265
- font-weight: var(--progressbar-danger-label-font-weight);
266
- line-height: var(--progressbar-danger-label-line-height);
267
- }
268
- .progress.danger .progress-value {
269
- color: var(--progressbar-danger-value);
270
- font-family: var(--progressbar-danger-value-font-family);
271
- font-size: var(--progressbar-danger-value-font-size);
272
- font-weight: var(--progressbar-danger-value-font-weight);
273
- line-height: var(--progressbar-danger-value-line-height);
274
- }
275
- .progress.danger .progress-track {
276
- background: var(--progressbar-danger-track-surface);
277
- border-color: var(--progressbar-danger-track-border);
278
- border-width: var(--progressbar-danger-track-border-width);
279
- border-radius: var(--progressbar-danger-radius);
280
- height: var(--progressbar-danger-track-height);
281
- }
282
- .progress-fill.danger {
283
- background: var(--progressbar-danger-fill);
284
- border-radius: var(--progressbar-danger-radius);
285
- }
286
-
287
- /* Info */
288
- .progress.info .progress-label > span {
289
- color: var(--progressbar-info-label);
290
- font-family: var(--progressbar-info-label-font-family);
291
- font-size: var(--progressbar-info-label-font-size);
292
- font-weight: var(--progressbar-info-label-font-weight);
293
- line-height: var(--progressbar-info-label-line-height);
294
- }
295
- .progress.info .progress-value {
296
- color: var(--progressbar-info-value);
297
- font-family: var(--progressbar-info-value-font-family);
298
- font-size: var(--progressbar-info-value-font-size);
299
- font-weight: var(--progressbar-info-value-font-weight);
300
- line-height: var(--progressbar-info-value-line-height);
301
- }
302
- .progress.info .progress-track {
303
- background: var(--progressbar-info-track-surface);
304
- border-color: var(--progressbar-info-track-border);
305
- border-width: var(--progressbar-info-track-border-width);
306
- border-radius: var(--progressbar-info-radius);
307
- height: var(--progressbar-info-track-height);
308
- }
309
- .progress-fill.info {
310
- background: var(--progressbar-info-fill);
311
- border-radius: var(--progressbar-info-radius);
312
- }
313
-
314
- .progress-icon {
315
- grid-area: icon;
316
- align-self: center;
317
- color: var(--text-success);
318
- font-size: var(--icon-size-md);
319
- line-height: 1;
320
- }
321
125
  </style>
@@ -13,6 +13,9 @@
13
13
  value?: string;
14
14
  disabled?: boolean;
15
15
  forceHoverValue?: string | null;
16
+ /** Visual size. `small` cascades `--segmentedcontrol-*-small-*` tokens
17
+ through the default token names so per-state rules pick them up. */
18
+ size?: 'default' | 'small';
16
19
  /** Selection callback. Preferred over `on:change` from 0.5.0 onward. */
17
20
  onchange?: (value: string) => void;
18
21
  }
@@ -22,6 +25,7 @@
22
25
  value = $bindable(''),
23
26
  disabled = false,
24
27
  forceHoverValue = null,
28
+ size = 'default',
25
29
  onchange
26
30
  }: Props = $props();
27
31
 
@@ -35,7 +39,7 @@
35
39
  }
36
40
  </script>
37
41
 
38
- <div class="segmented-control" class:is-disabled={disabled} role="radiogroup">
42
+ <div class="segmented-control" class:is-disabled={disabled} class:small={size === 'small'} role="radiogroup">
39
43
  {#each segments as seg, i (seg.value)}
40
44
  {#if i > 0}
41
45
  <span class="segment-divider" aria-hidden="true"></span>
@@ -68,10 +72,15 @@
68
72
  --segmentedcontrol-bar-padding: var(--space-4);
69
73
  --segmentedcontrol-bar-gap: var(--space-8);
70
74
 
71
- /* Divider (line between non-selected options) */
75
+ /* Divider (line between non-selected options). Inset is the top + bottom
76
+ margin trimmed from the divider; 0 = bar-height divider. */
72
77
  --segmentedcontrol-divider-color: var(--border-neutral);
73
78
  --segmentedcontrol-divider-thickness: var(--border-width-1);
74
- --segmentedcontrol-divider-height: var(--space-12);
79
+ --segmentedcontrol-divider-inset: var(--space-6);
80
+
81
+ /* Option (inner button) — shape applies to every state */
82
+ --segmentedcontrol-option-padding: var(--space-8);
83
+ --segmentedcontrol-option-gap: var(--space-8);
75
84
 
76
85
  /* Option — default */
77
86
  --segmentedcontrol-option-text: var(--text-primary);
@@ -90,7 +99,6 @@
90
99
  --segmentedcontrol-option-hover-text-font-weight: var(--font-weight-normal);
91
100
  --segmentedcontrol-option-hover-text-line-height: var(--line-height-md);
92
101
  --segmentedcontrol-option-hover-icon: var(--text-secondary);
93
- --segmentedcontrol-option-hover-icon-size: var(--icon-size-md);
94
102
 
95
103
  /* Selected (inner pill) — looks the same hovered or not */
96
104
  --segmentedcontrol-selected-surface: var(--surface-success-high);
@@ -100,7 +108,6 @@
100
108
  --segmentedcontrol-selected-text-font-weight: var(--font-weight-semibold);
101
109
  --segmentedcontrol-selected-text-line-height: var(--line-height-md);
102
110
  --segmentedcontrol-selected-icon: var(--text-secondary);
103
- --segmentedcontrol-selected-icon-size: var(--icon-size-md);
104
111
  --segmentedcontrol-selected-border: var(--border-success);
105
112
  --segmentedcontrol-selected-border-width: var(--border-width-1);
106
113
  --segmentedcontrol-selected-radius: var(--radius-md);
@@ -113,7 +120,21 @@
113
120
  --segmentedcontrol-disabled-text-font-weight: var(--font-weight-light);
114
121
  --segmentedcontrol-disabled-text-line-height: var(--line-height-md);
115
122
  --segmentedcontrol-disabled-icon: var(--text-tertiary);
116
- --segmentedcontrol-disabled-icon-size: var(--icon-size-md);
123
+
124
+ /* Small size — overrides for geometry + typography. Per-state colors and
125
+ font-weight stay shared with default; only the size-driven properties
126
+ differ. The `.small` rule below rebinds the default tokens to these
127
+ values so existing state-specific cascades flow through unchanged. */
128
+ --segmentedcontrol-bar-small-padding: var(--space-2);
129
+ --segmentedcontrol-bar-small-radius: var(--radius-md);
130
+ --segmentedcontrol-divider-small-inset: var(--space-4);
131
+ --segmentedcontrol-divider-small-thickness: var(--border-width-1);
132
+ --segmentedcontrol-option-small-padding: var(--space-6);
133
+ --segmentedcontrol-option-small-gap: var(--space-6);
134
+ --segmentedcontrol-option-small-icon-size: var(--icon-size-sm);
135
+ --segmentedcontrol-option-small-text-font-size: var(--font-size-sm);
136
+ --segmentedcontrol-option-small-text-line-height: var(--line-height-sm);
137
+ --segmentedcontrol-selected-small-radius: var(--radius-sm);
117
138
  }
118
139
 
119
140
  .segmented-control {
@@ -126,6 +147,50 @@
126
147
  border-radius: var(--segmentedcontrol-bar-radius);
127
148
  }
128
149
 
150
+ /* Small size modifier — rebinds the default tokens to their `-small-*`
151
+ counterparts. Per-state cascades (selected/hover/disabled typography,
152
+ icon size) all read through these default names, so rebinding them
153
+ here is enough — no per-state small token explosion. Per-side padding
154
+ overrides are rebound too so split-padding edits at small don't leak
155
+ through to default size. Font-weight and color are intentionally NOT
156
+ rebound: weight differences are state-driven (selected = semibold),
157
+ colors are state-driven too. */
158
+ .segmented-control.small {
159
+ --segmentedcontrol-bar-padding: var(--segmentedcontrol-bar-small-padding);
160
+ --segmentedcontrol-bar-padding-top: var(--segmentedcontrol-bar-small-padding-top);
161
+ --segmentedcontrol-bar-padding-right: var(--segmentedcontrol-bar-small-padding-right);
162
+ --segmentedcontrol-bar-padding-bottom: var(--segmentedcontrol-bar-small-padding-bottom);
163
+ --segmentedcontrol-bar-padding-left: var(--segmentedcontrol-bar-small-padding-left);
164
+ --segmentedcontrol-bar-radius: var(--segmentedcontrol-bar-small-radius);
165
+
166
+ --segmentedcontrol-divider-inset: var(--segmentedcontrol-divider-small-inset);
167
+ --segmentedcontrol-divider-thickness: var(--segmentedcontrol-divider-small-thickness);
168
+
169
+ --segmentedcontrol-option-padding: var(--segmentedcontrol-option-small-padding);
170
+ --segmentedcontrol-option-padding-top: var(--segmentedcontrol-option-small-padding-top);
171
+ --segmentedcontrol-option-padding-right: var(--segmentedcontrol-option-small-padding-right);
172
+ --segmentedcontrol-option-padding-bottom: var(--segmentedcontrol-option-small-padding-bottom);
173
+ --segmentedcontrol-option-padding-left: var(--segmentedcontrol-option-small-padding-left);
174
+ --segmentedcontrol-option-gap: var(--segmentedcontrol-option-small-gap);
175
+
176
+ /* Icon size has a single source-of-truth token now; text size/line-height
177
+ still need per-state rebinds because typography genuinely varies per
178
+ state (selected = semibold, default = normal). */
179
+ --segmentedcontrol-option-icon-size: var(--segmentedcontrol-option-small-icon-size);
180
+
181
+ --segmentedcontrol-option-text-font-size: var(--segmentedcontrol-option-small-text-font-size);
182
+ --segmentedcontrol-selected-text-font-size: var(--segmentedcontrol-option-small-text-font-size);
183
+ --segmentedcontrol-option-hover-text-font-size: var(--segmentedcontrol-option-small-text-font-size);
184
+ --segmentedcontrol-disabled-text-font-size: var(--segmentedcontrol-option-small-text-font-size);
185
+
186
+ --segmentedcontrol-option-text-line-height: var(--segmentedcontrol-option-small-text-line-height);
187
+ --segmentedcontrol-selected-text-line-height: var(--segmentedcontrol-option-small-text-line-height);
188
+ --segmentedcontrol-option-hover-text-line-height: var(--segmentedcontrol-option-small-text-line-height);
189
+ --segmentedcontrol-disabled-text-line-height: var(--segmentedcontrol-option-small-text-line-height);
190
+
191
+ --segmentedcontrol-selected-radius: var(--segmentedcontrol-selected-small-radius);
192
+ }
193
+
129
194
  /* Font + color properties are declared once on `.segment` and rebound per
130
195
  state via the `--_*` custom properties below. State classes only change
131
196
  the bindings; the actual `font-*` declarations never move. When two
@@ -144,8 +209,8 @@
144
209
 
145
210
  display: inline-flex;
146
211
  align-items: center;
147
- gap: var(--space-8);
148
- padding: var(--space-6) var(--space-16);
212
+ gap: var(--segmentedcontrol-option-gap);
213
+ @include themed-padding(--segmentedcontrol-option-padding, $h: 2);
149
214
  background: transparent;
150
215
  border: 0;
151
216
  border-radius: var(--segmentedcontrol-selected-radius);
@@ -165,13 +230,17 @@
165
230
  transition: color var(--duration-150);
166
231
  }
167
232
 
168
- /* Short centered divider between adjacent segments. Negative margins absorb
169
- the surrounding flex gap so seg-to-seg distance stays var(--bar-gap). */
233
+ /* Divider between adjacent segments. Stretches to the bar's cross-axis size
234
+ by inheriting the parent's `align-items: stretch`; an explicit margin-block
235
+ trims top + bottom so "Full" (0 inset) gives a bar-height line and larger
236
+ insets give shorter ones. Avoids the percentage-height collapse that bit us
237
+ when the divider was `align-self: center; height: 100%`.
238
+ Negative inline margins absorb the surrounding flex gap so seg-to-seg
239
+ distance stays var(--bar-gap). */
170
240
  .segment-divider {
171
- align-self: center;
172
241
  flex-shrink: 0;
173
242
  width: var(--segmentedcontrol-divider-thickness);
174
- height: var(--segmentedcontrol-divider-height);
243
+ margin-block: var(--segmentedcontrol-divider-inset);
175
244
  margin-inline: calc(
176
245
  var(--segmentedcontrol-bar-gap) * -0.5 - var(--segmentedcontrol-divider-thickness) * 0.5
177
246
  );
@@ -187,7 +256,6 @@
187
256
  --_text-weight: var(--segmentedcontrol-option-hover-text-font-weight);
188
257
  --_text-line-height: var(--segmentedcontrol-option-hover-text-line-height);
189
258
  --_icon-color: var(--segmentedcontrol-option-hover-icon);
190
- --_icon-size: var(--segmentedcontrol-option-hover-icon-size);
191
259
  background: var(--segmentedcontrol-option-hover-surface);
192
260
  }
193
261
 
@@ -202,7 +270,6 @@
202
270
  --_text-weight: var(--segmentedcontrol-selected-text-font-weight);
203
271
  --_text-line-height: var(--segmentedcontrol-selected-text-line-height);
204
272
  --_icon-color: var(--segmentedcontrol-selected-icon);
205
- --_icon-size: var(--segmentedcontrol-selected-icon-size);
206
273
  background: var(--segmentedcontrol-selected-surface);
207
274
  outline: var(--segmentedcontrol-selected-border-width) solid var(--segmentedcontrol-selected-border);
208
275
  outline-offset: calc(var(--segmentedcontrol-selected-border-width) * -1);
@@ -215,7 +282,6 @@
215
282
  --_text-weight: var(--segmentedcontrol-disabled-text-font-weight);
216
283
  --_text-line-height: var(--segmentedcontrol-disabled-text-line-height);
217
284
  --_icon-color: var(--segmentedcontrol-disabled-icon);
218
- --_icon-size: var(--segmentedcontrol-disabled-icon-size);
219
285
  background: var(--segmentedcontrol-disabled-surface);
220
286
  opacity: 0.4;
221
287
  cursor: not-allowed;