@motion-proto/live-tokens 0.94.3 → 0.95.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/.claude/skills/live-tokens-create-page/SKILL.md +7 -3
- package/CHANGELOG.md +97 -0
- package/README.md +6 -6
- package/dist-plugin/{chunk-7XSUHJUH.js → chunk-4J6JPSVS.js} +53 -2
- package/dist-plugin/{chunk-W5VQV32K.js → chunk-GYRULB2X.js} +1 -1
- package/dist-plugin/{chunk-ONYAIXCZ.js → chunk-QQASYPW7.js} +32 -9
- package/dist-plugin/index.cjs +598 -17
- package/dist-plugin/index.d.cts +9 -1
- package/dist-plugin/index.d.ts +9 -1
- package/dist-plugin/index.js +513 -6
- package/dist-plugin/migrateData/index.cjs +32 -9
- package/dist-plugin/migrateData/index.js +2 -2
- package/dist-plugin/setColors/index.cjs +32 -22
- package/dist-plugin/setColors/index.js +2 -15
- package/dist-plugin/setGeometry/index.cjs +32 -9
- package/dist-plugin/setGeometry/index.js +1 -1
- package/dist-plugin/tokensCssMigrations/index.cjs +53 -2
- package/dist-plugin/tokensCssMigrations/index.d.cts +9 -2
- package/dist-plugin/tokensCssMigrations/index.d.ts +9 -2
- package/dist-plugin/tokensCssMigrations/index.js +1 -1
- package/package.json +8 -3
- package/src/demo/Demo.svelte +39 -5
- package/src/demo/DemoBar.svelte +23 -5
- package/src/demo/FloatingTokenTags.css +33 -4
- package/src/demo/FloatingTokenTags.svelte +81 -68
- package/src/demo/Section.svelte +1 -7
- package/src/demo/SourceLinks.svelte +5 -4
- package/src/demo/TestingLoops.svelte +128 -19
- package/src/demo/evalResults.ts +7 -7
- package/src/demo/sections/SectionClaude.svelte +20 -13
- package/src/demo/sections/SectionFooter.svelte +4 -5
- package/src/demo/sections/SectionGetStarted.svelte +5 -6
- package/src/demo/sections/SectionHero.svelte +43 -23
- package/src/demo/sections/SectionKit.svelte +141 -45
- package/src/demo/sections/SectionLayers.svelte +3 -3
- package/src/demo/sections/SectionOffering.svelte +8 -23
- package/src/editor/bootstrap.ts +12 -6
- package/src/editor/component-editor/ImageEditor.svelte +1 -1
- package/src/editor/component-editor/ImageLightboxEditor.svelte +3 -4
- package/src/editor/component-editor/registration.ts +36 -0
- package/src/editor/component-editor/registry.ts +5 -12
- package/src/editor/component-editor/scaffolding/ShadowBackdrop.svelte +11 -2
- package/src/editor/component-editor/scaffolding/StateBlock.svelte +7 -0
- package/src/editor/component-editor/scaffolding/TokenLayout.svelte +1 -2
- package/src/editor/component-editor/scaffolding/VariantGroup.svelte +17 -2
- package/src/editor/core/store/editorPersistence.ts +6 -1
- package/src/editor/core/store/editorRenderer.ts +1 -4
- package/src/editor/core/store/editorStore.ts +5 -9
- package/src/editor/core/store/editorTypes.ts +2 -2
- package/src/editor/core/themes/migrations/2026-10-15-responsive-columns.ts +40 -0
- package/src/editor/core/themes/migrations/index.ts +2 -0
- package/src/editor/core/themes/slices/columns.ts +112 -42
- package/src/editor/docs/Docs.svelte +25 -22
- package/src/editor/docs/chapters.ts +1 -0
- package/src/editor/docs/content/editing-tokens.md +5 -3
- package/src/editor/docs/content/production-css.md +116 -0
- package/src/editor/docs/content/themes-workflow.md +2 -0
- package/src/editor/docs/content.generated.ts +3 -2
- package/src/editor/index.ts +2 -1
- package/src/editor/overlay/LiveEditorOverlay.svelte +67 -19
- package/src/editor/overlay/LiveTokensRouter.svelte +8 -4
- package/src/editor/pages/Editor.svelte +15 -1
- package/src/editor/pages/EditorShell.svelte +312 -99
- package/src/editor/skill-atlas/SkillAtlas.svelte +111 -24
- package/src/editor/skill-atlas/TreeCanvas.svelte +14 -0
- package/src/editor/skill-atlas/skillSources.generated.ts +1 -1
- package/src/editor/skill-atlas/trees/create-page.ts +24 -24
- package/src/editor/skill-atlas/wireLayout.ts +62 -0
- package/src/editor/ui/BezierCurveEditor.svelte +3 -0
- package/src/editor/ui/FontStackEditor.svelte +2 -2
- package/src/editor/ui/PaletteEditor.svelte +64 -6
- package/src/editor/ui/UIPaletteSelector.svelte +2 -0
- package/src/editor/ui/colors/ColorsTab.svelte +5 -2
- package/src/editor/ui/palette/OverridesPanel.svelte +1 -0
- package/src/editor/ui/palette/ScaleCurveEditor.svelte +127 -18
- package/src/editor/ui/sections/ColumnsSection.svelte +79 -49
- package/src/editor/ui/sections/ShadowsSection.svelte +14 -0
- package/src/editor/ui/sections/WashesSection.svelte +11 -0
- package/src/editor/ui/sketch/SketchTab.svelte +1 -1
- package/src/live-tokens/data/colors-and-type/autumn.json +1 -4
- package/src/live-tokens/data/colors-and-type/default.json +1 -4
- package/src/live-tokens/data/colors-and-type/halloween.json +1 -4
- package/src/live-tokens/data/colors-and-type/midnight-study.json +1 -4
- package/src/live-tokens/data/colors-and-type/ocean.json +1 -4
- package/src/live-tokens/data/colors-and-type/royal-velvet.json +1 -4
- package/src/live-tokens/data/colors-and-type/sketchy.json +1 -4
- package/src/live-tokens/data/colors-and-type/spring-meadow.json +1 -4
- package/src/live-tokens/data/colors-and-type/sunset.json +1 -4
- package/src/live-tokens/data/themes/autumn.json +1 -4
- package/src/live-tokens/data/themes/halloween.json +1 -4
- package/src/live-tokens/data/themes/midnight-study.json +1 -4
- package/src/live-tokens/data/themes/ocean.json +1 -4
- package/src/live-tokens/data/themes/royal-velvet.json +1 -4
- package/src/live-tokens/data/themes/sketchy.json +1 -4
- package/src/live-tokens/data/themes/spring-meadow.json +1 -4
- package/src/live-tokens/data/themes/sunset.json +1 -4
- package/src/live-tokens/data/tokens.generated.css +1 -4
- package/src/system/components/SectionDivider.svelte +4 -0
- package/src/system/styles/tokens.css +30 -4
- package/template/src/main.ts +2 -2
- package/template/src/pages/Home.svelte +11 -8
- package/template/vite.config.ts +7 -3
- package/src/system/assets/offering.webp +0 -0
- /package/dist-plugin/{chunk-O6GQ6GBH.js → chunk-A4TBP4MM.js} +0 -0
package/src/demo/evalResults.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
/** One arm of an eval: the same case run with or without the skills, and with or without the
|
|
1
|
+
/** One arm of an eval: the same case run with or without the skills, and with or without the lookup command. */
|
|
2
2
|
export interface EvalArm {
|
|
3
3
|
skills: boolean;
|
|
4
|
-
|
|
4
|
+
lookup: boolean;
|
|
5
5
|
rowsRight: string;
|
|
6
6
|
turns: string;
|
|
7
7
|
seconds: string;
|
|
@@ -28,7 +28,7 @@ export const pickComponentEval: EvalResult = {
|
|
|
28
28
|
arms: [
|
|
29
29
|
{
|
|
30
30
|
skills: true,
|
|
31
|
-
|
|
31
|
+
lookup: true,
|
|
32
32
|
rowsRight: '12 of 12 in all 3 runs',
|
|
33
33
|
turns: '9 to 10',
|
|
34
34
|
seconds: '46 to 76',
|
|
@@ -36,15 +36,15 @@ export const pickComponentEval: EvalResult = {
|
|
|
36
36
|
},
|
|
37
37
|
{
|
|
38
38
|
skills: false,
|
|
39
|
-
|
|
40
|
-
rowsRight: '12 of 12 in all 3 runs; 2 of 3 found the
|
|
39
|
+
lookup: true,
|
|
40
|
+
rowsRight: '12 of 12 in all 3 runs; 2 of 3 found the lookup on their own',
|
|
41
41
|
turns: '15 to 17',
|
|
42
42
|
seconds: '65 to 102',
|
|
43
43
|
cost: '$0.63 to $0.74',
|
|
44
44
|
},
|
|
45
45
|
{
|
|
46
46
|
skills: true,
|
|
47
|
-
|
|
47
|
+
lookup: false,
|
|
48
48
|
rowsRight: '12 of 12 in all 3 runs',
|
|
49
49
|
turns: '14 to 20',
|
|
50
50
|
seconds: '66 to 84',
|
|
@@ -52,7 +52,7 @@ export const pickComponentEval: EvalResult = {
|
|
|
52
52
|
},
|
|
53
53
|
{
|
|
54
54
|
skills: false,
|
|
55
|
-
|
|
55
|
+
lookup: false,
|
|
56
56
|
rowsRight: '11 of 12 in one run, which missed requirement 12',
|
|
57
57
|
turns: '17 to 20',
|
|
58
58
|
seconds: '113 to 169',
|
|
@@ -66,28 +66,26 @@
|
|
|
66
66
|
.claude {
|
|
67
67
|
grid-column: 1 / -1;
|
|
68
68
|
display: grid;
|
|
69
|
-
grid-template-columns:
|
|
70
|
-
column-gap: var(--columns-gutter);
|
|
69
|
+
grid-template-columns: subgrid;
|
|
71
70
|
row-gap: var(--space-8);
|
|
72
71
|
align-items: start;
|
|
73
|
-
margin-bottom: var(--space-96);
|
|
74
72
|
}
|
|
75
73
|
|
|
76
74
|
.claude :global(.section-divider) {
|
|
77
|
-
grid-column:
|
|
75
|
+
grid-column: var(--kit-content);
|
|
78
76
|
}
|
|
79
77
|
|
|
80
|
-
/* Panel sits on page columns 2
|
|
78
|
+
/* Panel sits on page columns 2 to 5; the copy starts on column 6, hard
|
|
81
79
|
against the panel's right edge. */
|
|
82
80
|
.panel-col {
|
|
83
|
-
grid-column: 2 /
|
|
81
|
+
grid-column: 2 / 6;
|
|
84
82
|
grid-row: 2;
|
|
85
83
|
align-self: start;
|
|
86
84
|
margin-top: var(--space-16);
|
|
87
85
|
}
|
|
88
86
|
|
|
89
87
|
.copy {
|
|
90
|
-
grid-column:
|
|
88
|
+
grid-column: 6 / -2;
|
|
91
89
|
grid-row: 2;
|
|
92
90
|
align-self: start;
|
|
93
91
|
display: flex;
|
|
@@ -98,7 +96,7 @@
|
|
|
98
96
|
|
|
99
97
|
.intro {
|
|
100
98
|
font-family: var(--font-sans);
|
|
101
|
-
font-size: var(--font-size
|
|
99
|
+
font-size: var(--body-xl-font-size);
|
|
102
100
|
line-height: var(--line-height-tighter);
|
|
103
101
|
font-weight: var(--font-weight-semibold);
|
|
104
102
|
color: var(--text-primary);
|
|
@@ -114,7 +112,7 @@
|
|
|
114
112
|
.install-caption {
|
|
115
113
|
margin: 0;
|
|
116
114
|
font-family: var(--font-sans);
|
|
117
|
-
font-size: var(--font-size
|
|
115
|
+
font-size: var(--body-md-font-size);
|
|
118
116
|
line-height: var(--line-height-normal);
|
|
119
117
|
color: var(--text-secondary);
|
|
120
118
|
}
|
|
@@ -171,17 +169,16 @@
|
|
|
171
169
|
|
|
172
170
|
.skill-name {
|
|
173
171
|
font-family: var(--font-sans);
|
|
174
|
-
font-size: var(--font-size
|
|
172
|
+
font-size: var(--heading-md-font-size);
|
|
175
173
|
font-weight: var(--font-weight-medium);
|
|
176
174
|
line-height: var(--line-height-normal);
|
|
177
175
|
color: var(--text-primary);
|
|
178
176
|
}
|
|
179
177
|
|
|
180
|
-
@media (max-width:
|
|
181
|
-
.claude :global(.section-divider),
|
|
178
|
+
@media (max-width: 1200px) {
|
|
182
179
|
.panel-col,
|
|
183
180
|
.copy {
|
|
184
|
-
grid-column:
|
|
181
|
+
grid-column: var(--kit-content);
|
|
185
182
|
}
|
|
186
183
|
|
|
187
184
|
.panel-col,
|
|
@@ -189,4 +186,14 @@
|
|
|
189
186
|
grid-row: auto;
|
|
190
187
|
}
|
|
191
188
|
}
|
|
189
|
+
|
|
190
|
+
@media (max-width: 600px) {
|
|
191
|
+
.atlas {
|
|
192
|
+
align-items: stretch;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.atlas-actions {
|
|
196
|
+
flex-direction: column;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
192
199
|
</style>
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
<style>
|
|
18
18
|
.provenance {
|
|
19
|
-
grid-column:
|
|
19
|
+
grid-column: var(--kit-content);
|
|
20
20
|
padding-top: var(--space-24);
|
|
21
21
|
border-top: var(--border-width-2) solid var(--border-neutral);
|
|
22
22
|
display: flex;
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
.license {
|
|
35
35
|
margin: 0;
|
|
36
36
|
font-family: var(--font-sans);
|
|
37
|
-
font-size: var(--font-size
|
|
37
|
+
font-size: var(--body-lg-font-size);
|
|
38
38
|
color: var(--text-secondary);
|
|
39
39
|
}
|
|
40
40
|
|
|
@@ -52,13 +52,12 @@
|
|
|
52
52
|
.copyright {
|
|
53
53
|
margin: 0;
|
|
54
54
|
font-family: var(--font-sans);
|
|
55
|
-
font-size: var(--font-size
|
|
55
|
+
font-size: var(--body-md-font-size);
|
|
56
56
|
color: var(--text-secondary);
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
@media (max-width:
|
|
59
|
+
@media (max-width: 1200px) {
|
|
60
60
|
.provenance {
|
|
61
|
-
grid-column: 1 / -1;
|
|
62
61
|
flex-direction: column;
|
|
63
62
|
align-items: flex-start;
|
|
64
63
|
gap: var(--space-24);
|
|
@@ -34,12 +34,11 @@ npm run dev`;
|
|
|
34
34
|
.get-started {
|
|
35
35
|
grid-column: 1 / -1;
|
|
36
36
|
display: grid;
|
|
37
|
-
grid-template-columns:
|
|
38
|
-
column-gap: var(--columns-gutter);
|
|
37
|
+
grid-template-columns: subgrid;
|
|
39
38
|
}
|
|
40
39
|
|
|
41
40
|
.gs-panel {
|
|
42
|
-
grid-column:
|
|
41
|
+
grid-column: var(--kit-content);
|
|
43
42
|
/* The .kit grid can stretch this section's row past its content (min-height:
|
|
44
43
|
100vh on a short page); keep the panel sized to its content regardless. */
|
|
45
44
|
align-self: start;
|
|
@@ -68,7 +67,7 @@ npm run dev`;
|
|
|
68
67
|
|
|
69
68
|
.intro {
|
|
70
69
|
font-family: var(--font-sans);
|
|
71
|
-
font-size: var(--font-size
|
|
70
|
+
font-size: var(--body-xl-font-size);
|
|
72
71
|
line-height: var(--line-height-tighter);
|
|
73
72
|
font-weight: var(--font-weight-semibold);
|
|
74
73
|
color: var(--text-primary);
|
|
@@ -91,9 +90,9 @@ npm run dev`;
|
|
|
91
90
|
overflow-y: hidden;
|
|
92
91
|
}
|
|
93
92
|
|
|
94
|
-
@media (max-width:
|
|
93
|
+
@media (max-width: 1200px) {
|
|
95
94
|
.columns {
|
|
96
|
-
grid-template-columns: 1fr;
|
|
95
|
+
grid-template-columns: minmax(0, 1fr);
|
|
97
96
|
align-items: stretch;
|
|
98
97
|
}
|
|
99
98
|
}
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
|
|
30
30
|
<p class="hero-tagline">
|
|
31
31
|
Design system authoring for Svelte.<br />
|
|
32
|
-
Edit tokens and components directly in the browser.<br />Ship plain CSS.
|
|
32
|
+
Edit tokens and components directly in the browser.<br class="desktop-break" /> Ship plain CSS.
|
|
33
33
|
</p>
|
|
34
34
|
</div>
|
|
35
35
|
|
|
@@ -63,18 +63,20 @@
|
|
|
63
63
|
.hero {
|
|
64
64
|
grid-column: 1 / -1;
|
|
65
65
|
position: relative;
|
|
66
|
-
padding: var(--space-48) 0
|
|
66
|
+
padding: var(--space-48) 0 0;
|
|
67
67
|
display: grid;
|
|
68
|
-
grid-template-columns:
|
|
69
|
-
column-gap: var(--columns-gutter);
|
|
68
|
+
grid-template-columns: subgrid;
|
|
70
69
|
}
|
|
71
70
|
|
|
71
|
+
/* The title runs across the kite on the full content width; the tagline
|
|
72
|
+
keeps the first five columns. */
|
|
72
73
|
.hero-text {
|
|
73
|
-
grid-column:
|
|
74
|
+
grid-column: var(--kit-content);
|
|
74
75
|
grid-row: 1;
|
|
75
|
-
display:
|
|
76
|
-
|
|
77
|
-
|
|
76
|
+
display: grid;
|
|
77
|
+
grid-template-columns: subgrid;
|
|
78
|
+
align-content: start;
|
|
79
|
+
row-gap: var(--space-16);
|
|
78
80
|
position: relative;
|
|
79
81
|
padding: var(--space-96) 0 0;
|
|
80
82
|
}
|
|
@@ -89,36 +91,37 @@
|
|
|
89
91
|
|
|
90
92
|
.hero-title {
|
|
91
93
|
font-family: var(--font-display);
|
|
92
|
-
font-size: var(--font-size
|
|
94
|
+
font-size: var(--display-xl-font-size);
|
|
93
95
|
font-weight: var(--font-weight-semibold);
|
|
94
96
|
font-variation-settings: 'opsz' 144, 'SOFT' 30;
|
|
95
97
|
color: var(--text-primary);
|
|
96
98
|
line-height: .9;
|
|
97
99
|
margin: 0;
|
|
100
|
+
grid-column: 1 / -1;
|
|
98
101
|
}
|
|
99
102
|
|
|
100
103
|
.hero-italic {
|
|
101
104
|
font-family: var(--heading-xl-font-family);
|
|
102
|
-
font-size: var(--font-size
|
|
105
|
+
font-size: var(--display-lg-font-size);
|
|
103
106
|
font-weight: var(--font-weight-normal);
|
|
104
107
|
color: var(--text-brand);
|
|
105
108
|
font-variation-settings: 'opsz' 144, 'SOFT' 100;
|
|
106
|
-
white-space: nowrap;
|
|
107
109
|
}
|
|
108
110
|
|
|
109
111
|
.hero-tagline {
|
|
110
112
|
font-family: var(--body-md-font-family);
|
|
111
|
-
font-size: var(--font-size
|
|
113
|
+
font-size: var(--body-2xl-font-size);
|
|
112
114
|
color: var(--text-primary);
|
|
113
115
|
line-height: 1.2;
|
|
114
|
-
|
|
116
|
+
grid-column: 1 / span 5;
|
|
115
117
|
margin: var(--space-8) 0 0;
|
|
118
|
+
text-wrap: pretty;
|
|
116
119
|
}
|
|
117
120
|
|
|
118
121
|
/* One row: the CTAs on the left rail, the credits on the right, sharing a
|
|
119
122
|
top edge so the buttons sit on the brand-mark line. */
|
|
120
123
|
.hero-actions {
|
|
121
|
-
grid-column:
|
|
124
|
+
grid-column: var(--kit-content);
|
|
122
125
|
grid-row: 2;
|
|
123
126
|
display: grid;
|
|
124
127
|
grid-template-columns: max-content 1fr;
|
|
@@ -148,7 +151,7 @@
|
|
|
148
151
|
|
|
149
152
|
.hero-byline {
|
|
150
153
|
font-family: var(--font-sans);
|
|
151
|
-
font-size: var(--font-size
|
|
154
|
+
font-size: var(--body-md-font-size);
|
|
152
155
|
font-weight: var(--font-weight-normal);
|
|
153
156
|
line-height: var(--line-height-normal);
|
|
154
157
|
color: var(--text-secondary);
|
|
@@ -164,20 +167,31 @@
|
|
|
164
167
|
text-decoration: underline;
|
|
165
168
|
}
|
|
166
169
|
|
|
167
|
-
@media (max-width:
|
|
168
|
-
|
|
169
|
-
|
|
170
|
+
@media (max-width: 1200px) {
|
|
171
|
+
/* Stacked, the illustration sits between the title and the tagline, so the
|
|
172
|
+
wrapper steps aside and each takes its own row of the hero grid. */
|
|
173
|
+
.hero-text {
|
|
174
|
+
display: contents;
|
|
175
|
+
}
|
|
176
|
+
.hero-title {
|
|
170
177
|
grid-row: 1;
|
|
171
|
-
height: 28rem;
|
|
172
178
|
}
|
|
173
|
-
.hero-
|
|
179
|
+
.hero-kite {
|
|
174
180
|
grid-column: 1 / -1;
|
|
175
181
|
grid-row: 2;
|
|
176
|
-
|
|
182
|
+
height: 28rem;
|
|
183
|
+
margin-top: var(--space-32);
|
|
177
184
|
}
|
|
178
|
-
.hero-
|
|
185
|
+
.hero-tagline {
|
|
179
186
|
grid-column: 1 / -1;
|
|
180
187
|
grid-row: 3;
|
|
188
|
+
margin-top: var(--space-16);
|
|
189
|
+
}
|
|
190
|
+
.desktop-break {
|
|
191
|
+
display: none;
|
|
192
|
+
}
|
|
193
|
+
.hero-actions {
|
|
194
|
+
grid-row: 4;
|
|
181
195
|
grid-template-columns: minmax(0, 1fr);
|
|
182
196
|
row-gap: var(--space-16);
|
|
183
197
|
margin-top: var(--space-12);
|
|
@@ -189,9 +203,15 @@
|
|
|
189
203
|
}
|
|
190
204
|
}
|
|
191
205
|
|
|
206
|
+
/* A phone wraps the second line, so the title steps up a size and the two
|
|
207
|
+
lines get a gap to tell them apart. */
|
|
192
208
|
@media (max-width: 600px) {
|
|
193
209
|
.hero-title {
|
|
194
|
-
font-size: var(--font-size
|
|
210
|
+
font-size: var(--display-2xl-font-size);
|
|
211
|
+
}
|
|
212
|
+
.hero-italic {
|
|
213
|
+
display: block;
|
|
214
|
+
margin-top: var(--space-16);
|
|
195
215
|
}
|
|
196
216
|
.hero-controls {
|
|
197
217
|
grid-template-columns: minmax(0, 1fr);
|
|
@@ -2,11 +2,15 @@
|
|
|
2
2
|
import Button from '../../system/components/Button.svelte';
|
|
3
3
|
import SectionDivider from '../../system/components/SectionDivider.svelte';
|
|
4
4
|
import SegmentedControl from '../../system/components/SegmentedControl.svelte';
|
|
5
|
+
import { MediaQuery } from 'svelte/reactivity';
|
|
5
6
|
import Panel from '../../system/components/Panel.svelte';
|
|
6
7
|
import Section from '../Section.svelte';
|
|
7
8
|
|
|
8
9
|
let { prose = true }: { prose?: boolean } = $props();
|
|
9
10
|
|
|
11
|
+
// Matches the demo's phone breakpoint in Demo.svelte.
|
|
12
|
+
const phone = new MediaQuery('max-width: 600px');
|
|
13
|
+
|
|
10
14
|
type Override = 'shape' | 'color';
|
|
11
15
|
|
|
12
16
|
let shape = $state(false);
|
|
@@ -35,39 +39,98 @@
|
|
|
35
39
|
return out;
|
|
36
40
|
})();
|
|
37
41
|
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
'
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
42
|
+
const FAMILIES = ['brand', 'accent', 'special', 'info', 'success', 'warning', 'danger'] as const;
|
|
43
|
+
type Family = (typeof FAMILIES)[number];
|
|
44
|
+
// The family each swapped variant paints from. Outline follows primary.
|
|
45
|
+
const SOURCES = { primary: 'brand', success: 'success', warning: 'warning', danger: 'danger' } as const;
|
|
46
|
+
type Swapped = keyof typeof SOURCES;
|
|
47
|
+
// Themes can give two families near-identical hues (Autumn's warning and
|
|
48
|
+
// accent share one), so a fixed swap can land on the colour it replaces.
|
|
49
|
+
const MIN_HUE_SHIFT = 60;
|
|
50
|
+
const SAME_HUE = 15;
|
|
51
|
+
|
|
52
|
+
let colorMap = $state<Record<Swapped, Family> | null>(null);
|
|
53
|
+
let colorStep = 0;
|
|
54
|
+
|
|
55
|
+
function familyHues(): Record<Family, number> {
|
|
56
|
+
const probe = document.createElement('span');
|
|
57
|
+
document.body.appendChild(probe);
|
|
58
|
+
const hues = {} as Record<Family, number>;
|
|
59
|
+
for (const family of FAMILIES) {
|
|
60
|
+
probe.style.color = `var(--color-${family}-500)`;
|
|
61
|
+
hues[family] = Number(/oklch\(\S+ \S+ ([\d.]+)/.exec(getComputedStyle(probe).color)?.[1] ?? 0);
|
|
62
|
+
}
|
|
63
|
+
probe.remove();
|
|
64
|
+
return hues;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function hueGap(a: number, b: number): number {
|
|
68
|
+
const d = Math.abs(a - b) % 360;
|
|
69
|
+
return Math.min(d, 360 - d);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** Each variant takes a family far enough round the wheel from its own,
|
|
73
|
+
* on a hue no other variant has where the theme has enough, rotated by
|
|
74
|
+
* `step`. Hue, not family: two families can share one. */
|
|
75
|
+
function pickColorMap(step: number): Record<Swapped, Family> {
|
|
76
|
+
const hues = familyHues();
|
|
77
|
+
const used: number[] = [];
|
|
78
|
+
const map = {} as Record<Swapped, Family>;
|
|
79
|
+
for (const [variant, source] of Object.entries(SOURCES) as [Swapped, Family][]) {
|
|
80
|
+
const byGap = FAMILIES.filter((f) => f !== source).sort((a, b) => hueGap(hues[b], hues[source]) - hueGap(hues[a], hues[source]));
|
|
81
|
+
const far = byGap.filter((f) => hueGap(hues[f], hues[source]) >= MIN_HUE_SHIFT);
|
|
82
|
+
const pool = far.length > 0 ? far : byGap.slice(0, 1);
|
|
83
|
+
const rotated = pool.map((_, i) => pool[(i + step) % pool.length]);
|
|
84
|
+
map[variant] = rotated.find((f) => used.every((h) => hueGap(h, hues[f]) >= SAME_HUE)) ?? rotated[0];
|
|
85
|
+
used.push(hues[map[variant]]);
|
|
86
|
+
}
|
|
87
|
+
return map;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function nextColorMap(): Record<Swapped, Family> {
|
|
91
|
+
const current = JSON.stringify(colorMap);
|
|
92
|
+
for (let tries = 0; tries < FAMILIES.length; tries++) {
|
|
93
|
+
const map = pickColorMap(++colorStep);
|
|
94
|
+
if (JSON.stringify(map) !== current) return map;
|
|
95
|
+
}
|
|
96
|
+
return pickColorMap(colorStep);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function colorOverride({ primary: p, success: s, warning: w, danger: d }: Record<Swapped, Family>): Record<string, string> {
|
|
100
|
+
return {
|
|
101
|
+
'--button-primary-surface': `var(--surface-${p}-high)`,
|
|
102
|
+
'--button-primary-border': `var(--border-${p})`,
|
|
103
|
+
'--button-primary-hover-surface': `var(--surface-${p}-higher)`,
|
|
104
|
+
'--button-primary-hover-border': `var(--border-${p}-strong)`,
|
|
105
|
+
|
|
106
|
+
'--button-outline-border': `var(--border-${p})`,
|
|
107
|
+
'--button-outline-text': `var(--text-${p})`,
|
|
108
|
+
'--button-outline-hover-border': `var(--border-${p}-strong)`,
|
|
109
|
+
|
|
110
|
+
'--button-success-surface': `var(--surface-${s}-low)`,
|
|
111
|
+
'--button-success-border': `var(--border-${s})`,
|
|
112
|
+
'--button-success-text': `var(--text-${s})`,
|
|
113
|
+
'--button-success-hover-surface': `var(--surface-${s}-higher)`,
|
|
114
|
+
'--button-success-hover-border': `var(--border-${s}-strong)`,
|
|
115
|
+
|
|
116
|
+
'--button-warning-surface': `var(--surface-${w}-low)`,
|
|
117
|
+
'--button-warning-border': `var(--border-${w})`,
|
|
118
|
+
'--button-warning-text': `var(--text-${w})`,
|
|
119
|
+
'--button-warning-hover-surface': `var(--surface-${w}-high)`,
|
|
120
|
+
'--button-warning-hover-border': `var(--border-${w}-medium)`,
|
|
121
|
+
|
|
122
|
+
'--button-danger-surface': `var(--surface-${d}-low)`,
|
|
123
|
+
'--button-danger-border': `var(--border-${d})`,
|
|
124
|
+
'--button-danger-text': `var(--text-${d})`,
|
|
125
|
+
'--button-danger-hover-surface': `var(--surface-${d}-high)`,
|
|
126
|
+
'--button-danger-hover-border': `var(--border-${d}-medium)`,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
66
129
|
|
|
67
130
|
let stageStyle = $derived.by(() => {
|
|
68
131
|
const merged: Record<string, string> = {};
|
|
69
132
|
if (shape) Object.assign(merged, shapeOverride);
|
|
70
|
-
if (color) Object.assign(merged, colorOverride);
|
|
133
|
+
if (color && colorMap) Object.assign(merged, colorOverride(colorMap));
|
|
71
134
|
return Object.entries(merged)
|
|
72
135
|
.map(([k, v]) => `${k}: ${v}`)
|
|
73
136
|
.join('; ');
|
|
@@ -96,9 +159,11 @@
|
|
|
96
159
|
lastApplied = shape ? 'shape' : color ? 'color' : null;
|
|
97
160
|
return;
|
|
98
161
|
}
|
|
162
|
+
// Every press of Color is a new swap, so it never toggles back off.
|
|
99
163
|
if (v === 'color') {
|
|
100
|
-
|
|
101
|
-
|
|
164
|
+
colorMap = nextColorMap();
|
|
165
|
+
color = true;
|
|
166
|
+
lastApplied = 'color';
|
|
102
167
|
}
|
|
103
168
|
}
|
|
104
169
|
</script>
|
|
@@ -156,7 +221,7 @@
|
|
|
156
221
|
<div class="swap-block">
|
|
157
222
|
<div class="swap-control">
|
|
158
223
|
<SectionDivider title="Swap tokens with a click" variant="sm" />
|
|
159
|
-
<SegmentedControl {segments} value={activeSegment} onchange={handleSelect} />
|
|
224
|
+
<SegmentedControl {segments} value={activeSegment} onchange={handleSelect} size={phone.current ? 'small' : 'default'} />
|
|
160
225
|
</div>
|
|
161
226
|
|
|
162
227
|
<Panel style={stageStyle}>
|
|
@@ -184,7 +249,7 @@
|
|
|
184
249
|
columns and the row stops at column 9, leaving column 10 open on the right. */
|
|
185
250
|
.kit-grid {
|
|
186
251
|
display: grid;
|
|
187
|
-
grid-template-columns: repeat(calc(var(--columns-count) - 2), 1fr);
|
|
252
|
+
grid-template-columns: repeat(calc(var(--columns-count) - 2), minmax(0, 1fr));
|
|
188
253
|
column-gap: var(--columns-gutter);
|
|
189
254
|
row-gap: var(--space-32);
|
|
190
255
|
}
|
|
@@ -202,7 +267,8 @@
|
|
|
202
267
|
padding: 0 0 var(--space-12);
|
|
203
268
|
}
|
|
204
269
|
|
|
205
|
-
/* Title
|
|
270
|
+
/* Title and body match the Card in the Layers section at desktop sizes, and
|
|
271
|
+
take the text styles' phone sizes below it. */
|
|
206
272
|
.kit-icon {
|
|
207
273
|
font-size: var(--icon-size-2xl);
|
|
208
274
|
color: var(--text-primary);
|
|
@@ -211,7 +277,7 @@
|
|
|
211
277
|
.kit-title {
|
|
212
278
|
color: var(--text-primary);
|
|
213
279
|
font-family: var(--font-sans);
|
|
214
|
-
font-size: var(--font-size
|
|
280
|
+
font-size: var(--heading-md-font-size);
|
|
215
281
|
font-weight: var(--font-weight-medium);
|
|
216
282
|
line-height: var(--line-height-normal);
|
|
217
283
|
}
|
|
@@ -219,7 +285,7 @@
|
|
|
219
285
|
.kit-body {
|
|
220
286
|
padding: var(--space-12) 0 0;
|
|
221
287
|
font-family: var(--font-sans);
|
|
222
|
-
font-size: var(--font-size
|
|
288
|
+
font-size: var(--body-xl-font-size);
|
|
223
289
|
line-height: var(--line-height-normal);
|
|
224
290
|
font-weight: var(--font-weight-normal);
|
|
225
291
|
color: var(--text-secondary);
|
|
@@ -270,7 +336,7 @@
|
|
|
270
336
|
--sketch-hatch-color: var(--color-brand-500);
|
|
271
337
|
}
|
|
272
338
|
|
|
273
|
-
/* The head only carries a surface of its own when stacked (see the
|
|
339
|
+
/* The head only carries a surface of its own when stacked (see the 1200
|
|
274
340
|
breakpoint). Here it has none, and --sketch-fill inherits, so without this
|
|
275
341
|
the layer would draw the lead's wash a second time behind the head. */
|
|
276
342
|
.kit-lead .kit-head {
|
|
@@ -288,14 +354,14 @@
|
|
|
288
354
|
}
|
|
289
355
|
|
|
290
356
|
.kit-lead .kit-title {
|
|
291
|
-
font-size: var(--font-size
|
|
357
|
+
font-size: var(--heading-xl-font-size);
|
|
292
358
|
font-weight: var(--font-weight-bold);
|
|
293
359
|
}
|
|
294
360
|
|
|
295
361
|
.kit-lead .kit-body {
|
|
296
362
|
grid-column: 4 / span 6;
|
|
297
363
|
padding: var(--space-32) 0;
|
|
298
|
-
font-size: var(--font-size
|
|
364
|
+
font-size: var(--body-2xl-font-size);
|
|
299
365
|
color: var(--text-primary);
|
|
300
366
|
}
|
|
301
367
|
|
|
@@ -304,7 +370,7 @@
|
|
|
304
370
|
.kit-preview {
|
|
305
371
|
margin-top: var(--space-32);
|
|
306
372
|
display: grid;
|
|
307
|
-
grid-template-columns: repeat(calc(var(--columns-count) - 2), 1fr);
|
|
373
|
+
grid-template-columns: repeat(calc(var(--columns-count) - 2), minmax(0, 1fr));
|
|
308
374
|
column-gap: var(--columns-gutter);
|
|
309
375
|
}
|
|
310
376
|
|
|
@@ -349,7 +415,7 @@
|
|
|
349
415
|
.stage-eyebrow {
|
|
350
416
|
align-self: center;
|
|
351
417
|
font-family: var(--font-sans);
|
|
352
|
-
font-size: var(--font-size
|
|
418
|
+
font-size: var(--body-md-font-size);
|
|
353
419
|
font-weight: var(--font-weight-medium);
|
|
354
420
|
letter-spacing: var(--letter-spacing-wide);
|
|
355
421
|
text-transform: uppercase;
|
|
@@ -373,9 +439,10 @@
|
|
|
373
439
|
justify-content: center;
|
|
374
440
|
}
|
|
375
441
|
|
|
376
|
-
@media (max-width:
|
|
377
|
-
.kit-grid
|
|
378
|
-
|
|
442
|
+
@media (max-width: 1200px) {
|
|
443
|
+
.kit-grid,
|
|
444
|
+
.kit-preview {
|
|
445
|
+
grid-template-columns: minmax(0, 1fr);
|
|
379
446
|
}
|
|
380
447
|
.kit-item {
|
|
381
448
|
grid-column: auto;
|
|
@@ -404,7 +471,36 @@
|
|
|
404
471
|
}
|
|
405
472
|
.kit-lead .kit-body {
|
|
406
473
|
padding: var(--space-16) var(--space-20);
|
|
407
|
-
font-size: var(--font-size
|
|
474
|
+
font-size: var(--body-xl-font-size);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/* Phone: the lead's text lines up with the page margin, and the head's tint
|
|
479
|
+
bleeds out to the screen edges. The tint is a border-image outset, which
|
|
480
|
+
paints past the box without widening the section. The swap control spans
|
|
481
|
+
the column, its segments sharing the width. */
|
|
482
|
+
@media (max-width: 600px) {
|
|
483
|
+
.swap-control {
|
|
484
|
+
margin-top: var(--space-8);
|
|
485
|
+
flex-direction: column;
|
|
486
|
+
align-items: stretch;
|
|
487
|
+
gap: var(--space-8);
|
|
488
|
+
}
|
|
489
|
+
.swap-control :global(.segmented-control) {
|
|
490
|
+
display: flex;
|
|
491
|
+
}
|
|
492
|
+
.swap-control :global(.segment) {
|
|
493
|
+
flex: 1 1 0;
|
|
494
|
+
min-width: 0;
|
|
495
|
+
justify-content: center;
|
|
496
|
+
}
|
|
497
|
+
.kit-lead .kit-head {
|
|
498
|
+
padding-inline: 0;
|
|
499
|
+
background: none;
|
|
500
|
+
border-image: conic-gradient(var(--kit-head-tint) 0 0) fill 0 / 0 / 0 var(--columns-margin);
|
|
501
|
+
}
|
|
502
|
+
.kit-lead .kit-body {
|
|
503
|
+
padding-inline: 0;
|
|
408
504
|
}
|
|
409
505
|
}
|
|
410
506
|
</style>
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
<style>
|
|
29
29
|
.arch {
|
|
30
30
|
display: grid;
|
|
31
|
-
grid-template-columns: repeat(2, 1fr);
|
|
31
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
32
32
|
column-gap: var(--columns-gutter);
|
|
33
33
|
row-gap: var(--space-32);
|
|
34
34
|
}
|
|
@@ -46,9 +46,9 @@
|
|
|
46
46
|
border-radius: var(--radius-sm);
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
@media (max-width:
|
|
49
|
+
@media (max-width: 1200px) {
|
|
50
50
|
.arch {
|
|
51
|
-
grid-template-columns: 1fr;
|
|
51
|
+
grid-template-columns: minmax(0, 1fr);
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
</style>
|