@motion-proto/live-tokens 0.9.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.
- package/README.md +50 -29
- package/dist-plugin/index.cjs +177 -125
- package/dist-plugin/index.d.cts +3 -2
- package/dist-plugin/index.d.ts +3 -2
- package/dist-plugin/index.js +177 -125
- package/package.json +4 -1
- package/src/editor/component-editor/BadgeEditor.svelte +44 -42
- package/src/editor/component-editor/ButtonEditor.svelte +224 -0
- package/src/editor/component-editor/CollapsibleSectionEditor.svelte +1 -7
- package/src/editor/component-editor/CornerBadgeEditor.svelte +44 -34
- package/src/editor/component-editor/ImageLightboxEditor.svelte +58 -0
- package/src/editor/component-editor/InputEditor.svelte +272 -0
- package/src/editor/component-editor/NotificationEditor.svelte +44 -65
- package/src/editor/component-editor/ProgressBarEditor.svelte +71 -87
- package/src/editor/component-editor/SegmentedControlEditor.svelte +98 -37
- package/src/editor/component-editor/SideNavigationEditor.svelte +342 -0
- package/src/editor/component-editor/registry.ts +35 -2
- package/src/editor/component-editor/scaffolding/ComponentFileManager.svelte +3 -2
- package/src/editor/component-editor/scaffolding/StateBlock.svelte +9 -10
- package/src/editor/component-editor/scaffolding/TokenLayout.svelte +60 -36
- package/src/editor/component-editor/scaffolding/VariantGroup.svelte +38 -1
- package/src/editor/component-editor/scaffolding/buildTypeGroupTokens.ts +1 -1
- package/src/editor/component-editor/scaffolding/siblings.ts +2 -2
- package/src/editor/component-editor/scaffolding/types.ts +2 -1
- package/src/editor/core/components/componentConfigService.ts +7 -6
- package/src/editor/core/manifests/manifestService.ts +5 -4
- package/src/editor/core/storage/apiBase.ts +15 -0
- package/src/editor/core/storage/files/versionedFileResourceClient.ts +1 -1
- package/src/editor/core/themes/migrations/2026-05-24-collapsiblesection-drop-active-state.ts +28 -0
- package/src/editor/core/themes/migrations/2026-05-24-progressbar-collapse-variants.ts +41 -0
- package/src/editor/core/themes/migrations/2026-05-24-promote-state-shared-tokens.ts +59 -0
- package/src/editor/core/themes/migrations/2026-05-24-segmentedcontrol-divider-inset.ts +29 -0
- package/src/editor/core/themes/migrations/2026-05-25-cornerbadge-flatten-variants.ts +46 -0
- package/src/editor/core/themes/migrations/index.ts +10 -0
- package/src/editor/core/themes/themeInit.ts +3 -2
- package/src/editor/core/themes/themeService.ts +3 -2
- package/src/editor/ui/UIEasingSelector.svelte +240 -0
- package/src/editor/ui/variantScales.ts +34 -0
- package/src/system/components/Button.svelte +34 -85
- package/src/system/components/CollapsibleSection.svelte +1 -48
- package/src/system/components/CornerBadge.svelte +72 -138
- package/src/system/components/ImageLightbox.svelte +578 -0
- package/src/system/components/Input.svelte +387 -0
- package/src/system/components/ProgressBar.svelte +62 -258
- package/src/system/components/SegmentedControl.svelte +81 -15
- package/src/system/components/SideNavigation.svelte +777 -0
- package/src/system/styles/tokens.css +43 -0
- package/src/system/styles/tokens.generated.css +4 -183
- package/src/editor/component-editor/StandardButtonsEditor.svelte +0 -190
|
@@ -45,6 +45,11 @@ import { componentMigration_2026_05_19_sectiondividerRichGradient } from './2026
|
|
|
45
45
|
import { componentMigration_2026_05_20_sectiondividerSlimVariants } from './2026-05-20-sectiondivider-slim-variants';
|
|
46
46
|
import { componentMigration_2026_05_21_sectiondividerSpacingToPadding } from './2026-05-21-sectiondivider-spacing-to-padding';
|
|
47
47
|
import { componentMigration_2026_05_22_sectiondividerIntrinsicsToCss } from './2026-05-22-sectiondivider-intrinsics-to-css';
|
|
48
|
+
import { componentMigration_2026_05_24_segmentedcontrolDividerInset } from './2026-05-24-segmentedcontrol-divider-inset';
|
|
49
|
+
import { componentMigration_2026_05_24_promoteStateSharedTokens } from './2026-05-24-promote-state-shared-tokens';
|
|
50
|
+
import { componentMigration_2026_05_24_progressbarCollapseVariants } from './2026-05-24-progressbar-collapse-variants';
|
|
51
|
+
import { componentMigration_2026_05_24_collapsiblesectionDropActiveState } from './2026-05-24-collapsiblesection-drop-active-state';
|
|
52
|
+
import { componentMigration_2026_05_25_cornerbadgeFlattenVariants } from './2026-05-25-cornerbadge-flatten-variants';
|
|
48
53
|
|
|
49
54
|
/**
|
|
50
55
|
* Registered migrations. Order in this array does not matter — the runner
|
|
@@ -64,6 +69,11 @@ export const MIGRATIONS: Migration[] = [
|
|
|
64
69
|
componentMigration_2026_05_20_sectiondividerSlimVariants,
|
|
65
70
|
componentMigration_2026_05_21_sectiondividerSpacingToPadding,
|
|
66
71
|
componentMigration_2026_05_22_sectiondividerIntrinsicsToCss,
|
|
72
|
+
componentMigration_2026_05_24_segmentedcontrolDividerInset,
|
|
73
|
+
componentMigration_2026_05_24_promoteStateSharedTokens,
|
|
74
|
+
componentMigration_2026_05_24_progressbarCollapseVariants,
|
|
75
|
+
componentMigration_2026_05_24_collapsiblesectionDropActiveState,
|
|
76
|
+
componentMigration_2026_05_25_cornerbadgeFlattenVariants,
|
|
67
77
|
];
|
|
68
78
|
|
|
69
79
|
function countFor(kind: 'theme' | 'component-config'): number {
|
|
@@ -5,6 +5,7 @@ import { applyFontSources, applyFontStacks } from '../fonts/fontLoader';
|
|
|
5
5
|
import { loadFromFile, seedComponentsFromApi } from '../store/editorStore';
|
|
6
6
|
import { getActiveComponentConfig } from '../components/componentConfigService';
|
|
7
7
|
import { safeFetch } from '../storage/storage';
|
|
8
|
+
import { API_BASE } from '../storage/apiBase';
|
|
8
9
|
|
|
9
10
|
interface ComponentSummaryDto {
|
|
10
11
|
name: string;
|
|
@@ -34,7 +35,7 @@ interface ListComponentsDto {
|
|
|
34
35
|
* `safeFetch` (instead of empty try/catch) to make the silence intentional.
|
|
35
36
|
*/
|
|
36
37
|
export async function initializeTheme(): Promise<void> {
|
|
37
|
-
const theme = await safeFetch<Theme>(
|
|
38
|
+
const theme = await safeFetch<Theme>(`${API_BASE}/themes/active`);
|
|
38
39
|
if (theme) {
|
|
39
40
|
migrateThemeFonts(theme);
|
|
40
41
|
loadFromFile(theme);
|
|
@@ -48,7 +49,7 @@ export async function initializeTheme(): Promise<void> {
|
|
|
48
49
|
activeFileName.set(fileName);
|
|
49
50
|
}
|
|
50
51
|
|
|
51
|
-
const list = await safeFetch<ListComponentsDto>(
|
|
52
|
+
const list = await safeFetch<ListComponentsDto>(`${API_BASE}/component-configs`);
|
|
52
53
|
if (list && Array.isArray(list.components)) {
|
|
53
54
|
const configs: Record<
|
|
54
55
|
string,
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
versionedFileResource,
|
|
6
6
|
sanitizeFileName as sanitizeFileNameImpl,
|
|
7
7
|
} from '../storage/files/versionedFileResourceClient';
|
|
8
|
+
import { API_BASE } from '../storage/apiBase';
|
|
8
9
|
import { loadFromFile as loadEditorState, toTheme, markSaved } from '../store/editorStore';
|
|
9
10
|
import { activeFileName } from '../store/editorConfigStore';
|
|
10
11
|
import { applyFontSources, applyFontStacks } from '../fonts/fontLoader';
|
|
@@ -12,7 +13,7 @@ import { migrateThemeFonts } from '../fonts/fontMigration';
|
|
|
12
13
|
|
|
13
14
|
// ── API helpers ──────────────────────────────────────────────
|
|
14
15
|
//
|
|
15
|
-
// All theme CRUD goes through `versionedFileResource(
|
|
16
|
+
// All theme CRUD goes through `versionedFileResource(`${API_BASE}/themes`)` —
|
|
16
17
|
// shared with `componentConfigService`'s per-component clients. Theme-specific
|
|
17
18
|
// response shapes (ThemeMeta list payload, ProductionInfo) are layered on top
|
|
18
19
|
// via the generic type parameters.
|
|
@@ -25,7 +26,7 @@ export interface ProductionInfo {
|
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
const themeResource = versionedFileResource<Theme, ThemeMeta, ProductionInfo>({
|
|
28
|
-
baseUrl:
|
|
29
|
+
baseUrl: `${API_BASE}/themes`,
|
|
29
30
|
});
|
|
30
31
|
|
|
31
32
|
export async function listThemes(): Promise<ThemeMeta[]> {
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { resolveAliasChain } from '../core/palettes/tokenRegistry';
|
|
3
|
+
import UITokenSelector from './UITokenSelector.svelte';
|
|
4
|
+
import UIOptionList from './UIOptionList.svelte';
|
|
5
|
+
import UIOptionItem from './UIOptionItem.svelte';
|
|
6
|
+
|
|
7
|
+
interface Props {
|
|
8
|
+
variable: string;
|
|
9
|
+
component?: string | undefined;
|
|
10
|
+
canBeLinked?: boolean;
|
|
11
|
+
disabled?: boolean;
|
|
12
|
+
selectionsLocked?: boolean;
|
|
13
|
+
onchange?: () => void;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
let {
|
|
17
|
+
variable,
|
|
18
|
+
component = undefined,
|
|
19
|
+
canBeLinked = false,
|
|
20
|
+
disabled = false,
|
|
21
|
+
selectionsLocked = false,
|
|
22
|
+
onchange,
|
|
23
|
+
}: Props = $props();
|
|
24
|
+
|
|
25
|
+
/** Family list mirrors easings.net's catalog. `linear` is the special-case
|
|
26
|
+
curve with no variant; all others take in/out/in-out. Keys are the suffix
|
|
27
|
+
portion of the corresponding `--ease-*` token name. */
|
|
28
|
+
const FAMILIES = [
|
|
29
|
+
{ key: 'linear', label: 'Linear' },
|
|
30
|
+
{ key: 'sine', label: 'Sine' },
|
|
31
|
+
{ key: 'quad', label: 'Quad' },
|
|
32
|
+
{ key: 'cubic', label: 'Cubic' },
|
|
33
|
+
{ key: 'quart', label: 'Quart' },
|
|
34
|
+
{ key: 'quint', label: 'Quint' },
|
|
35
|
+
{ key: 'expo', label: 'Expo' },
|
|
36
|
+
{ key: 'circ', label: 'Circ' },
|
|
37
|
+
{ key: 'back', label: 'Back' },
|
|
38
|
+
{ key: 'elastic', label: 'Elastic' },
|
|
39
|
+
{ key: 'bounce', label: 'Bounce' },
|
|
40
|
+
] as const;
|
|
41
|
+
type FamilyKey = typeof FAMILIES[number]['key'];
|
|
42
|
+
|
|
43
|
+
const VARIANTS = [
|
|
44
|
+
{ key: 'in', label: 'In' },
|
|
45
|
+
{ key: 'out', label: 'Out' },
|
|
46
|
+
{ key: 'in-out', label: 'In-Out' },
|
|
47
|
+
] as const;
|
|
48
|
+
type VariantKey = typeof VARIANTS[number]['key'];
|
|
49
|
+
|
|
50
|
+
const FAMILY_KEYS = new Set<string>(FAMILIES.map((f) => f.key));
|
|
51
|
+
const VARIANT_KEYS = new Set<string>(VARIANTS.map((v) => v.key));
|
|
52
|
+
|
|
53
|
+
let selector: UITokenSelector;
|
|
54
|
+
let chosenFamily: FamilyKey | null = $state(null);
|
|
55
|
+
let chosenVariant: VariantKey | null = $state(null);
|
|
56
|
+
let currentValue: string = $state('');
|
|
57
|
+
|
|
58
|
+
/** Parse `--ease-linear` or `--ease-<variant>-<family>` into its parts.
|
|
59
|
+
Returns nulls when the name doesn't match the ease-token convention. */
|
|
60
|
+
function parseEaseToken(varName: string): { family: FamilyKey | null; variant: VariantKey | null } {
|
|
61
|
+
if (varName === '--ease-linear') return { family: 'linear', variant: null };
|
|
62
|
+
const m = varName.match(/^--ease-(in-out|in|out)-([a-z]+)$/);
|
|
63
|
+
if (!m) return { family: null, variant: null };
|
|
64
|
+
const variant = m[1] as VariantKey;
|
|
65
|
+
const family = m[2] as FamilyKey;
|
|
66
|
+
if (!FAMILY_KEYS.has(family) || family === 'linear') return { family: null, variant: null };
|
|
67
|
+
if (!VARIANT_KEYS.has(variant)) return { family: null, variant: null };
|
|
68
|
+
return { family, variant };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function buildEaseToken(family: FamilyKey, variant: VariantKey | null): string | null {
|
|
72
|
+
if (family === 'linear') return '--ease-linear';
|
|
73
|
+
if (!variant) return null;
|
|
74
|
+
return `--ease-${variant}-${family}`;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Pull the var() reference out of `var(--ease-...)`, returns the inner name. */
|
|
78
|
+
function parseRef(raw: string): string | null {
|
|
79
|
+
const m = raw.match(/var\((--ease-[a-z-]+)\)/);
|
|
80
|
+
return m ? m[1] : null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function readResolved() {
|
|
84
|
+
currentValue = getComputedStyle(document.documentElement).getPropertyValue(variable).trim();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function initFromCurrent() {
|
|
88
|
+
readResolved();
|
|
89
|
+
const raw = document.documentElement.style.getPropertyValue(variable).trim();
|
|
90
|
+
if (raw) {
|
|
91
|
+
const inner = parseRef(raw);
|
|
92
|
+
if (inner) {
|
|
93
|
+
const parts = parseEaseToken(inner);
|
|
94
|
+
chosenFamily = parts.family;
|
|
95
|
+
chosenVariant = parts.variant;
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
for (const alias of resolveAliasChain(variable)) {
|
|
100
|
+
const parts = parseEaseToken(alias);
|
|
101
|
+
if (parts.family) {
|
|
102
|
+
chosenFamily = parts.family;
|
|
103
|
+
chosenVariant = parts.variant;
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
chosenFamily = null;
|
|
108
|
+
chosenVariant = null;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function handleReset() {
|
|
112
|
+
chosenFamily = null;
|
|
113
|
+
chosenVariant = null;
|
|
114
|
+
readResolved();
|
|
115
|
+
onchange?.();
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** Commit (family, variant) — writes the override if both halves are valid;
|
|
119
|
+
for non-linear families without a variant yet, defaults to `out`. Closes
|
|
120
|
+
the dropdown only when a full token name was produced. */
|
|
121
|
+
function commit(family: FamilyKey, variant: VariantKey | null, close: () => void): void {
|
|
122
|
+
let v = variant;
|
|
123
|
+
if (family !== 'linear' && !v) v = 'out';
|
|
124
|
+
const target = buildEaseToken(family, v);
|
|
125
|
+
if (!target) return;
|
|
126
|
+
if (target === variable) {
|
|
127
|
+
selector.writeOverride(null);
|
|
128
|
+
} else {
|
|
129
|
+
selector.writeOverride(target);
|
|
130
|
+
}
|
|
131
|
+
chosenFamily = family;
|
|
132
|
+
chosenVariant = family === 'linear' ? null : v;
|
|
133
|
+
readResolved();
|
|
134
|
+
close();
|
|
135
|
+
onchange?.();
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function selectFamily(key: FamilyKey, close: () => void) {
|
|
139
|
+
commit(key, chosenVariant, close);
|
|
140
|
+
}
|
|
141
|
+
function selectVariant(key: VariantKey, close: () => void) {
|
|
142
|
+
if (!chosenFamily || chosenFamily === 'linear') return;
|
|
143
|
+
commit(chosenFamily, key, close);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
let lastSeenVariable: string | null = null;
|
|
147
|
+
$effect(() => {
|
|
148
|
+
if (variable !== lastSeenVariable) {
|
|
149
|
+
lastSeenVariable = variable;
|
|
150
|
+
initFromCurrent();
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
let familyLabel = $derived(FAMILIES.find((f) => f.key === chosenFamily)?.label ?? '');
|
|
155
|
+
let variantLabel = $derived(VARIANTS.find((v) => v.key === chosenVariant)?.label ?? '');
|
|
156
|
+
let triggerTitleText = $derived(
|
|
157
|
+
chosenFamily === 'linear'
|
|
158
|
+
? 'Linear'
|
|
159
|
+
: chosenFamily && chosenVariant
|
|
160
|
+
? `${variantLabel} ${familyLabel}`
|
|
161
|
+
: chosenFamily
|
|
162
|
+
? `${familyLabel} —`
|
|
163
|
+
: '',
|
|
164
|
+
);
|
|
165
|
+
</script>
|
|
166
|
+
|
|
167
|
+
<UITokenSelector
|
|
168
|
+
bind:this={selector}
|
|
169
|
+
{variable}
|
|
170
|
+
{component}
|
|
171
|
+
{canBeLinked}
|
|
172
|
+
{disabled}
|
|
173
|
+
{selectionsLocked}
|
|
174
|
+
dropdownMinWidth="18rem"
|
|
175
|
+
onreset={handleReset}
|
|
176
|
+
onvarChange={initFromCurrent}
|
|
177
|
+
>
|
|
178
|
+
{#snippet triggerTitle()}{triggerTitleText}{/snippet}
|
|
179
|
+
{#snippet triggerMeta()}{currentValue || '—'}{/snippet}
|
|
180
|
+
|
|
181
|
+
{#snippet children({ close })}
|
|
182
|
+
<div class="ease-grid" class:no-variants={chosenFamily === 'linear'}>
|
|
183
|
+
<div class="ease-col">
|
|
184
|
+
<span class="ease-col-label">Curve</span>
|
|
185
|
+
<UIOptionList>
|
|
186
|
+
{#each FAMILIES as fam (fam.key)}
|
|
187
|
+
<UIOptionItem
|
|
188
|
+
active={chosenFamily === fam.key}
|
|
189
|
+
onclick={() => selectFamily(fam.key, close)}
|
|
190
|
+
>
|
|
191
|
+
{#snippet label()}{fam.label}{/snippet}
|
|
192
|
+
</UIOptionItem>
|
|
193
|
+
{/each}
|
|
194
|
+
</UIOptionList>
|
|
195
|
+
</div>
|
|
196
|
+
{#if chosenFamily && chosenFamily !== 'linear'}
|
|
197
|
+
<div class="ease-col">
|
|
198
|
+
<span class="ease-col-label">Variant</span>
|
|
199
|
+
<UIOptionList>
|
|
200
|
+
{#each VARIANTS as v (v.key)}
|
|
201
|
+
<UIOptionItem
|
|
202
|
+
active={chosenVariant === v.key}
|
|
203
|
+
onclick={() => selectVariant(v.key, close)}
|
|
204
|
+
>
|
|
205
|
+
{#snippet label()}{v.label}{/snippet}
|
|
206
|
+
</UIOptionItem>
|
|
207
|
+
{/each}
|
|
208
|
+
</UIOptionList>
|
|
209
|
+
</div>
|
|
210
|
+
{/if}
|
|
211
|
+
</div>
|
|
212
|
+
{/snippet}
|
|
213
|
+
</UITokenSelector>
|
|
214
|
+
|
|
215
|
+
<style>
|
|
216
|
+
.ease-grid {
|
|
217
|
+
display: grid;
|
|
218
|
+
grid-template-columns: 1fr 1fr;
|
|
219
|
+
gap: var(--ui-space-8);
|
|
220
|
+
min-width: 18rem;
|
|
221
|
+
}
|
|
222
|
+
.ease-grid.no-variants {
|
|
223
|
+
grid-template-columns: 1fr;
|
|
224
|
+
}
|
|
225
|
+
.ease-col {
|
|
226
|
+
display: flex;
|
|
227
|
+
flex-direction: column;
|
|
228
|
+
gap: var(--ui-space-4);
|
|
229
|
+
min-width: 0;
|
|
230
|
+
}
|
|
231
|
+
.ease-col-label {
|
|
232
|
+
padding: var(--ui-space-4) var(--ui-space-8) 0;
|
|
233
|
+
font-size: var(--ui-font-size-xs);
|
|
234
|
+
font-weight: var(--ui-font-weight-semibold);
|
|
235
|
+
color: var(--ui-text-tertiary);
|
|
236
|
+
font-family: var(--ui-font-mono);
|
|
237
|
+
text-transform: uppercase;
|
|
238
|
+
letter-spacing: 0.04em;
|
|
239
|
+
}
|
|
240
|
+
</style>
|
|
@@ -106,3 +106,37 @@ export const DIVIDER_HEIGHT: VariantScaleEntry = {
|
|
|
106
106
|
{ key: 'full', label: 'Full', value: '100%' },
|
|
107
107
|
],
|
|
108
108
|
};
|
|
109
|
+
|
|
110
|
+
/** Used by `*-duration` variables (CSS transition timing). Pulls keys directly
|
|
111
|
+
* from the shared `--duration-*` scale in tokens.css — labels mirror the token
|
|
112
|
+
* slugs so the picker reflects the utility token namespace, no synthetic names. */
|
|
113
|
+
export const DURATION: VariantScaleEntry = {
|
|
114
|
+
varPrefix: '--duration-',
|
|
115
|
+
options: [
|
|
116
|
+
{ key: '75', label: '75', value: '75ms' },
|
|
117
|
+
{ key: '150', label: '150', value: '150ms' },
|
|
118
|
+
{ key: '200', label: '200', value: '200ms' },
|
|
119
|
+
{ key: '300', label: '300', value: '300ms' },
|
|
120
|
+
{ key: '500', label: '500', value: '500ms' },
|
|
121
|
+
{ key: '750', label: '750', value: '750ms' },
|
|
122
|
+
{ key: '1000', label: '1000', value: '1000ms' },
|
|
123
|
+
],
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
/** Used by `*-divider-inset` variables (margin-block trimmed off a stretched
|
|
127
|
+
* divider). Labels describe the resulting divider, not the inset value: 0
|
|
128
|
+
* inset = bar-height divider ("Full"); larger insets = shorter divider.
|
|
129
|
+
* Replaces the percentage-height approach that collapsed to 0 in
|
|
130
|
+
* auto-height flex parents. */
|
|
131
|
+
export const DIVIDER_INSET: VariantScaleEntry = {
|
|
132
|
+
varPrefix: '--space-',
|
|
133
|
+
options: [
|
|
134
|
+
{ key: '0', label: 'Full', value: '0px' },
|
|
135
|
+
{ key: '2', label: 'Tall', value: '0.125rem' },
|
|
136
|
+
{ key: '4', label: 'Large', value: '0.25rem' },
|
|
137
|
+
{ key: '6', label: 'Medium', value: '0.375rem' },
|
|
138
|
+
{ key: '8', label: 'Short', value: '0.5rem' },
|
|
139
|
+
{ key: '12', label: 'XS', value: '0.75rem' },
|
|
140
|
+
{ key: '16', label: 'Tiny', value: '1rem' },
|
|
141
|
+
],
|
|
142
|
+
};
|
|
@@ -87,15 +87,9 @@
|
|
|
87
87
|
--button-primary-hover-surface: var(--surface-brand-higher);
|
|
88
88
|
--button-primary-hover-text: var(--text-primary);
|
|
89
89
|
--button-primary-hover-border: var(--border-brand-strong);
|
|
90
|
-
--button-primary-hover-border-width: var(--border-width-1);
|
|
91
|
-
--button-primary-hover-radius: var(--radius-md);
|
|
92
|
-
--button-primary-hover-padding: var(--space-8);
|
|
93
90
|
--button-primary-disabled-surface: var(--color-neutral-700);
|
|
94
91
|
--button-primary-disabled-text: var(--text-tertiary);
|
|
95
92
|
--button-primary-disabled-border: var(--border-neutral-faint);
|
|
96
|
-
--button-primary-disabled-border-width: var(--border-width-1);
|
|
97
|
-
--button-primary-disabled-radius: var(--radius-md);
|
|
98
|
-
--button-primary-disabled-padding: var(--space-8);
|
|
99
93
|
--button-primary-icon-size: var(--icon-size-sm);
|
|
100
94
|
|
|
101
95
|
/* Secondary */
|
|
@@ -112,15 +106,9 @@
|
|
|
112
106
|
--button-secondary-hover-surface: var(--surface-neutral-higher);
|
|
113
107
|
--button-secondary-hover-text: var(--text-primary);
|
|
114
108
|
--button-secondary-hover-border: var(--border-neutral-strong);
|
|
115
|
-
--button-secondary-hover-border-width: var(--border-width-1);
|
|
116
|
-
--button-secondary-hover-radius: var(--radius-md);
|
|
117
|
-
--button-secondary-hover-padding: var(--space-8);
|
|
118
109
|
--button-secondary-disabled-surface: var(--color-neutral-700);
|
|
119
110
|
--button-secondary-disabled-text: var(--text-tertiary);
|
|
120
111
|
--button-secondary-disabled-border: var(--border-neutral-faint);
|
|
121
|
-
--button-secondary-disabled-border-width: var(--border-width-1);
|
|
122
|
-
--button-secondary-disabled-radius: var(--radius-md);
|
|
123
|
-
--button-secondary-disabled-padding: var(--space-8);
|
|
124
112
|
--button-secondary-icon-size: var(--icon-size-sm);
|
|
125
113
|
|
|
126
114
|
/* Outline */
|
|
@@ -137,16 +125,10 @@
|
|
|
137
125
|
--button-outline-hover-surface: var(--surface-neutral-lower);
|
|
138
126
|
--button-outline-hover-text: var(--text-primary);
|
|
139
127
|
--button-outline-hover-border: var(--border-neutral-strong);
|
|
140
|
-
--button-outline-hover-border-width: var(--border-width-1);
|
|
141
|
-
--button-outline-hover-radius: var(--radius-md);
|
|
142
|
-
--button-outline-hover-padding: var(--space-8);
|
|
143
128
|
--button-outline-active-surface: var(--hover);
|
|
144
129
|
--button-outline-disabled-surface: var(--color-transparent);
|
|
145
130
|
--button-outline-disabled-text: var(--text-tertiary);
|
|
146
131
|
--button-outline-disabled-border: var(--border-neutral-faint);
|
|
147
|
-
--button-outline-disabled-border-width: var(--border-width-1);
|
|
148
|
-
--button-outline-disabled-radius: var(--radius-md);
|
|
149
|
-
--button-outline-disabled-padding: var(--space-8);
|
|
150
132
|
--button-outline-icon-size: var(--icon-size-sm);
|
|
151
133
|
|
|
152
134
|
/* Success */
|
|
@@ -163,15 +145,9 @@
|
|
|
163
145
|
--button-success-hover-surface: var(--surface-success-higher);
|
|
164
146
|
--button-success-hover-text: var(--text-primary);
|
|
165
147
|
--button-success-hover-border: var(--border-success-strong);
|
|
166
|
-
--button-success-hover-border-width: var(--border-width-2);
|
|
167
|
-
--button-success-hover-radius: var(--radius-md);
|
|
168
|
-
--button-success-hover-padding: var(--space-8);
|
|
169
148
|
--button-success-disabled-surface: var(--color-neutral-700);
|
|
170
149
|
--button-success-disabled-text: var(--text-tertiary);
|
|
171
150
|
--button-success-disabled-border: var(--border-neutral-faint);
|
|
172
|
-
--button-success-disabled-border-width: var(--border-width-2);
|
|
173
|
-
--button-success-disabled-radius: var(--radius-md);
|
|
174
|
-
--button-success-disabled-padding: var(--space-8);
|
|
175
151
|
--button-success-icon-size: var(--icon-size-sm);
|
|
176
152
|
|
|
177
153
|
/* Danger */
|
|
@@ -188,15 +164,9 @@
|
|
|
188
164
|
--button-danger-hover-surface: var(--surface-danger-high);
|
|
189
165
|
--button-danger-hover-text: var(--text-primary);
|
|
190
166
|
--button-danger-hover-border: var(--border-danger-medium);
|
|
191
|
-
--button-danger-hover-border-width: var(--border-width-2);
|
|
192
|
-
--button-danger-hover-radius: var(--radius-md);
|
|
193
|
-
--button-danger-hover-padding: var(--space-8);
|
|
194
167
|
--button-danger-disabled-surface: var(--color-neutral-700);
|
|
195
168
|
--button-danger-disabled-text: var(--text-tertiary);
|
|
196
169
|
--button-danger-disabled-border: var(--border-neutral-faint);
|
|
197
|
-
--button-danger-disabled-border-width: var(--border-width-2);
|
|
198
|
-
--button-danger-disabled-radius: var(--radius-md);
|
|
199
|
-
--button-danger-disabled-padding: var(--space-8);
|
|
200
170
|
--button-danger-icon-size: var(--icon-size-sm);
|
|
201
171
|
|
|
202
172
|
/* Warning */
|
|
@@ -213,16 +183,20 @@
|
|
|
213
183
|
--button-warning-hover-surface: var(--surface-warning-high);
|
|
214
184
|
--button-warning-hover-text: var(--text-primary);
|
|
215
185
|
--button-warning-hover-border: var(--border-warning-medium);
|
|
216
|
-
--button-warning-hover-border-width: var(--border-width-2);
|
|
217
|
-
--button-warning-hover-radius: var(--radius-md);
|
|
218
|
-
--button-warning-hover-padding: var(--space-8);
|
|
219
186
|
--button-warning-disabled-surface: var(--color-neutral-700);
|
|
220
187
|
--button-warning-disabled-text: var(--text-tertiary);
|
|
221
188
|
--button-warning-disabled-border: var(--border-neutral-faint);
|
|
222
|
-
--button-warning-disabled-border-width: var(--border-width-2);
|
|
223
|
-
--button-warning-disabled-radius: var(--radius-md);
|
|
224
|
-
--button-warning-disabled-padding: var(--space-8);
|
|
225
189
|
--button-warning-icon-size: var(--icon-size-sm);
|
|
190
|
+
|
|
191
|
+
/* Small size — shared across all variants. The `.small` rule below reads
|
|
192
|
+
these tokens directly (no per-variant rebind needed, since small
|
|
193
|
+
currently looks the same regardless of variant). Per-side padding
|
|
194
|
+
overrides power split-padding edits at small. */
|
|
195
|
+
--button-small-padding: var(--space-6);
|
|
196
|
+
--button-small-text-font-size: var(--font-size-xs);
|
|
197
|
+
--button-small-text-font-weight: var(--font-weight-normal);
|
|
198
|
+
--button-small-text-line-height: var(--line-height-sm);
|
|
199
|
+
--button-small-icon-size: var(--font-size-xs);
|
|
226
200
|
}
|
|
227
201
|
|
|
228
202
|
.button {
|
|
@@ -298,9 +272,7 @@
|
|
|
298
272
|
&:hover:not(:disabled),
|
|
299
273
|
&.force-hover:not(:disabled) {
|
|
300
274
|
background: var(--button-primary-hover-surface);
|
|
301
|
-
border: var(--button-primary-hover-border
|
|
302
|
-
border-radius: var(--button-primary-hover-radius);
|
|
303
|
-
@include themed-padding(--button-primary-hover-padding, $h: 2);
|
|
275
|
+
border-color: var(--button-primary-hover-border);
|
|
304
276
|
color: var(--button-primary-hover-text);
|
|
305
277
|
}
|
|
306
278
|
|
|
@@ -310,9 +282,7 @@
|
|
|
310
282
|
|
|
311
283
|
&:disabled {
|
|
312
284
|
background: var(--button-primary-disabled-surface);
|
|
313
|
-
border: var(--button-primary-disabled-border
|
|
314
|
-
border-radius: var(--button-primary-disabled-radius);
|
|
315
|
-
@include themed-padding(--button-primary-disabled-padding, $h: 2);
|
|
285
|
+
border-color: var(--button-primary-disabled-border);
|
|
316
286
|
color: var(--button-primary-disabled-text);
|
|
317
287
|
}
|
|
318
288
|
}
|
|
@@ -340,17 +310,13 @@
|
|
|
340
310
|
&:hover:not(:disabled),
|
|
341
311
|
&.force-hover:not(:disabled) {
|
|
342
312
|
background: var(--button-secondary-hover-surface);
|
|
343
|
-
border: var(--button-secondary-hover-border
|
|
344
|
-
border-radius: var(--button-secondary-hover-radius);
|
|
345
|
-
@include themed-padding(--button-secondary-hover-padding, $h: 2);
|
|
313
|
+
border-color: var(--button-secondary-hover-border);
|
|
346
314
|
color: var(--button-secondary-hover-text);
|
|
347
315
|
}
|
|
348
316
|
|
|
349
317
|
&:disabled {
|
|
350
318
|
background: var(--button-secondary-disabled-surface);
|
|
351
|
-
border: var(--button-secondary-disabled-border
|
|
352
|
-
border-radius: var(--button-secondary-disabled-radius);
|
|
353
|
-
@include themed-padding(--button-secondary-disabled-padding, $h: 2);
|
|
319
|
+
border-color: var(--button-secondary-disabled-border);
|
|
354
320
|
color: var(--button-secondary-disabled-text);
|
|
355
321
|
}
|
|
356
322
|
}
|
|
@@ -378,9 +344,7 @@
|
|
|
378
344
|
&:hover:not(:disabled),
|
|
379
345
|
&.force-hover:not(:disabled) {
|
|
380
346
|
background: var(--button-outline-hover-surface);
|
|
381
|
-
border: var(--button-outline-hover-border
|
|
382
|
-
border-radius: var(--button-outline-hover-radius);
|
|
383
|
-
@include themed-padding(--button-outline-hover-padding, $h: 2);
|
|
347
|
+
border-color: var(--button-outline-hover-border);
|
|
384
348
|
color: var(--button-outline-hover-text);
|
|
385
349
|
}
|
|
386
350
|
|
|
@@ -390,9 +354,7 @@
|
|
|
390
354
|
|
|
391
355
|
&:disabled {
|
|
392
356
|
background: var(--button-outline-disabled-surface);
|
|
393
|
-
border: var(--button-outline-disabled-border
|
|
394
|
-
border-radius: var(--button-outline-disabled-radius);
|
|
395
|
-
@include themed-padding(--button-outline-disabled-padding, $h: 2);
|
|
357
|
+
border-color: var(--button-outline-disabled-border);
|
|
396
358
|
color: var(--button-outline-disabled-text);
|
|
397
359
|
}
|
|
398
360
|
}
|
|
@@ -420,17 +382,13 @@
|
|
|
420
382
|
&:hover:not(:disabled),
|
|
421
383
|
&.force-hover:not(:disabled) {
|
|
422
384
|
background: var(--button-success-hover-surface);
|
|
423
|
-
border: var(--button-success-hover-border
|
|
424
|
-
border-radius: var(--button-success-hover-radius);
|
|
425
|
-
@include themed-padding(--button-success-hover-padding, $h: 2);
|
|
385
|
+
border-color: var(--button-success-hover-border);
|
|
426
386
|
color: var(--button-success-hover-text);
|
|
427
387
|
}
|
|
428
388
|
|
|
429
389
|
&:disabled {
|
|
430
390
|
background: var(--button-success-disabled-surface);
|
|
431
|
-
border: var(--button-success-disabled-border
|
|
432
|
-
border-radius: var(--button-success-disabled-radius);
|
|
433
|
-
@include themed-padding(--button-success-disabled-padding, $h: 2);
|
|
391
|
+
border-color: var(--button-success-disabled-border);
|
|
434
392
|
color: var(--button-success-disabled-text);
|
|
435
393
|
}
|
|
436
394
|
}
|
|
@@ -458,17 +416,13 @@
|
|
|
458
416
|
&:hover:not(:disabled),
|
|
459
417
|
&.force-hover:not(:disabled) {
|
|
460
418
|
background: var(--button-danger-hover-surface);
|
|
461
|
-
border: var(--button-danger-hover-border
|
|
462
|
-
border-radius: var(--button-danger-hover-radius);
|
|
463
|
-
@include themed-padding(--button-danger-hover-padding, $h: 2);
|
|
419
|
+
border-color: var(--button-danger-hover-border);
|
|
464
420
|
color: var(--button-danger-hover-text);
|
|
465
421
|
}
|
|
466
422
|
|
|
467
423
|
&:disabled {
|
|
468
424
|
background: var(--button-danger-disabled-surface);
|
|
469
|
-
border: var(--button-danger-disabled-border
|
|
470
|
-
border-radius: var(--button-danger-disabled-radius);
|
|
471
|
-
@include themed-padding(--button-danger-disabled-padding, $h: 2);
|
|
425
|
+
border-color: var(--button-danger-disabled-border);
|
|
472
426
|
color: var(--button-danger-disabled-text);
|
|
473
427
|
}
|
|
474
428
|
}
|
|
@@ -496,37 +450,32 @@
|
|
|
496
450
|
&:hover:not(:disabled),
|
|
497
451
|
&.force-hover:not(:disabled) {
|
|
498
452
|
background: var(--button-warning-hover-surface);
|
|
499
|
-
border: var(--button-warning-hover-border
|
|
500
|
-
border-radius: var(--button-warning-hover-radius);
|
|
501
|
-
@include themed-padding(--button-warning-hover-padding, $h: 2);
|
|
453
|
+
border-color: var(--button-warning-hover-border);
|
|
502
454
|
color: var(--button-warning-hover-text);
|
|
503
455
|
}
|
|
504
456
|
|
|
505
457
|
&:disabled {
|
|
506
458
|
background: var(--button-warning-disabled-surface);
|
|
507
|
-
border: var(--button-warning-disabled-border
|
|
508
|
-
border-radius: var(--button-warning-disabled-radius);
|
|
509
|
-
@include themed-padding(--button-warning-disabled-padding, $h: 2);
|
|
459
|
+
border-color: var(--button-warning-disabled-border);
|
|
510
460
|
color: var(--button-warning-disabled-text);
|
|
511
461
|
}
|
|
512
462
|
}
|
|
513
463
|
|
|
514
|
-
// Small size modifier (applies to any variant).
|
|
515
|
-
//
|
|
516
|
-
//
|
|
517
|
-
//
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
&.small
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
font-
|
|
524
|
-
|
|
525
|
-
line-height: var(--line-height-sm);
|
|
464
|
+
// Small size modifier (applies to any variant). Variants only set padding
|
|
465
|
+
// once in their base rule and never override per-state, so a single
|
|
466
|
+
// selector here is enough — `.small` declared after the variant block
|
|
467
|
+
// wins on source order. themed-padding with $h: 2 mirrors the variant
|
|
468
|
+
// base rule; per-side `--button-small-padding-*` tokens (registered by
|
|
469
|
+
// the editor) feed split edits through the mixin.
|
|
470
|
+
&.small {
|
|
471
|
+
@include themed-padding(--button-small-padding, $h: 2);
|
|
472
|
+
font-size: var(--button-small-text-font-size);
|
|
473
|
+
font-weight: var(--button-small-text-font-weight);
|
|
474
|
+
line-height: var(--button-small-text-line-height);
|
|
526
475
|
}
|
|
527
476
|
|
|
528
477
|
&.small :global(i) {
|
|
529
|
-
font-size: var(--
|
|
478
|
+
font-size: var(--button-small-icon-size);
|
|
530
479
|
font-weight: var(--font-weight-semibold);
|
|
531
480
|
}
|
|
532
481
|
|