Skip to content

Commit 07beeaa

Browse files
committed
fix(configurator): resync panels with the live token API
Audited every --sf-* reference in configurator/src against docs/api-index.json. Several panels had drifted from the framework and were editing tokens that no longer exist, or missing tokens that do: Colors panel - add --sf-gradient-action to the gradient editors. The framework ships a gradient for all four brand families and the preview catalog's GRADS list already renders an "action" swatch, but the panel offered no editor for it. - --sf-color-danger-source-dark default was oklch(0.73 0.198 12); the framework ships oklch(0.71 0.198 12), so the panel seeded and compared against a value the framework never had. - add the -tint rung to the status families. The 5%-alpha tint was extended to all ten families (#572); the panel still enumerated four rungs and its comment asserted no others existed. Motion panel - the Stagger section wrote --sf-animation-delay-1…5, which were removed when .sf-stagger landed. Every control in that section was inert. It now edits the replacement knob, --sf-stagger-step, and the delay preview applies --sf-motion-scale for display only (core/motion.css applies it for real). Misc panel - remove the Scroll behavior section: --sf-scroll-behavior is not a framework token and no CSS has ever read it, so both buttons were inert. If smooth scrolling should be configurable, it needs a real token in core first. Preview sections - --sf-leading-loose does not exist (the scale is tight/snug/normal/relaxed); the leading specimen now demonstrates --sf-leading-relaxed. - drop the dead --sf-color-canvas needle from the surface-token filter. svelte-check clean, 196 configurator tests pass, curation + preview-coverage gates pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017Lm2xzYUfVcsxL3EhTemDd
1 parent b97151f commit 07beeaa

5 files changed

Lines changed: 38 additions & 57 deletions

File tree

configurator/src/components/DomainPanel.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@
8787
{:else if domain === "shadows"}
8888
<ShadowsPanel {overrides} {onSet} {onReset} />
8989
{:else if domain === "motion"}
90-
<MotionPanel {overrides} {onSet} {onReset} {onBulkChange} />
90+
<MotionPanel {overrides} {onSet} {onReset} />
9191
{:else if domain === "effects"}
9292
<EffectsPanel {overrides} {onSet} {onReset} />
9393
{:else if domain === "macros"}

configurator/src/components/panels/ColorsPanel.svelte

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@
5757
{ name: "--sf-gradient-tertiary", label: "Tertiary", group: "brand", kind: "angle", space: "oklch", angle: 135, dir: "right",
5858
stop1: "var(--sf-color-tertiary)", stop2: "oklch(from var(--sf-color-tertiary) calc(l - 0.08) c h)",
5959
formula: "linear-gradient(in oklch 135deg, var(--sf-color-tertiary), oklch(from var(--sf-color-tertiary) calc(l - 0.08) c h))" },
60+
{ name: "--sf-gradient-action", label: "Action", group: "brand", kind: "angle", space: "oklch", angle: 135, dir: "right",
61+
stop1: "var(--sf-color-action)", stop2: "oklch(from var(--sf-color-action) calc(l - 0.08) c h)",
62+
formula: "linear-gradient(in oklch 135deg, var(--sf-color-action), oklch(from var(--sf-color-action) calc(l - 0.08) c h))" },
6063
{ name: "--sf-gradient-brand", label: "Brand", group: "brand", kind: "angle", space: "oklch", angle: 135, dir: "right",
6164
stop1: "var(--sf-color-primary)", stop2: "oklch(from var(--sf-color-primary) l c calc(h + 30))",
6265
formula: "linear-gradient(in oklch 135deg, var(--sf-color-primary), oklch(from var(--sf-color-primary) l c calc(h + 30)))" },
@@ -108,7 +111,7 @@
108111
{ name: "--sf-color-info-source-light", label: "Info", side: "light", default: "oklch(0.48 0.18 235)", colorKey: "info" },
109112
{ name: "--sf-color-info-source-dark", label: "Info", side: "dark", default: "oklch(0.71 0.162 235)", colorKey: "info" },
110113
{ name: "--sf-color-danger-source-light", label: "Danger", side: "light", default: "oklch(0.48 0.22 12)", colorKey: "danger" },
111-
{ name: "--sf-color-danger-source-dark", label: "Danger", side: "dark", default: "oklch(0.73 0.198 12)", colorKey: "danger" },
114+
{ name: "--sf-color-danger-source-dark", label: "Danger", side: "dark", default: "oklch(0.71 0.198 12)", colorKey: "danger" },
112115
];
113116
114117
// Baked per-step ramp curve — mirrors core/tokens.css: how far each step
@@ -178,11 +181,13 @@
178181
const PALETTE_COLOR_KEYS = [...BRAND_COLOR_KEYS, "base"];
179182
180183
// Status families (success/warning/info/danger) have NO numeric 50-950
181-
// ramp in the framework — only these four derived values actually exist
182-
// (core/tokens.css: resolved color + -subtle/-muted alpha washes + a
183-
// light-dark() -strong shift). Mirror that here instead of faking a ramp.
184+
// ramp in the framework — only these five derived values actually exist
185+
// (core/tokens.css: resolved color + -tint/-subtle/-muted alpha washes at
186+
// 0.05/0.12/0.3 + a light-dark() -strong shift). Mirror that here instead of
187+
// faking a ramp.
184188
const STATUS_VARIANTS: { label: string; expr: (key: string) => string }[] = [
185189
{ label: "Base", expr: (k) => `var(--sf-color-${k})` },
190+
{ label: "Tint", expr: (k) => `var(--sf-color-${k}-tint)` },
186191
{ label: "Subtle", expr: (k) => `var(--sf-color-${k}-subtle)` },
187192
{ label: "Muted", expr: (k) => `var(--sf-color-${k}-muted)` },
188193
{ label: "Strong", expr: (k) => `var(--sf-color-${k}-strong)` },

configurator/src/components/panels/MiscPanel.svelte

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,6 @@
2323
{ label: "Tooltip", token: "--sf-z-tooltip", note: "Inline tooltips", def: 1060 },
2424
];
2525
26-
const SCROLL_BEHAVIORS = [
27-
{ label: "Smooth", value: "smooth" },
28-
{ label: "Auto", value: "auto" },
29-
];
30-
3126
const SIZE_TOKENS = [
3227
{ label: "XS", token: "--sf-size-xs", default: 1.5 },
3328
{ label: "S", token: "--sf-size-s", default: 2 },
@@ -43,14 +38,12 @@
4338
}
4439
4540
let touchTarget = $derived(parseNum(overrides["--sf-touch-target"], 44, "px"));
46-
let scrollBehavior = $derived(overrides["--sf-scroll-behavior"] ?? "smooth");
4741
let zBaseOffset = $derived(parseNum(overrides["--sf-z-base"], 0));
4842
let caretColor = $derived(overrides["--sf-caret-color"] ?? "");
4943
let underlineOffset = $derived(parseNum(overrides["--sf-link-underline-offset"]?.replace("em",""), 0.15));
5044
let underlineThickness = $derived(overrides["--sf-link-underline-thickness"] ?? "auto");
5145
5246
let showTouchTarget = $state(false);
53-
let showScrollBehavior = $state(false);
5447
let showZIndex = $state(false);
5548
let showTextSelection = $state(false);
5649
let showComponentSizes = $state(false);
@@ -93,26 +86,6 @@
9386

9487
<div class="h-px bg-black/6 dark:bg-white/6"></div>
9588

96-
<!-- SCROLL BEHAVIOR -->
97-
<Section title="Scroll behavior" bind:open={showScrollBehavior}>
98-
<div class="flex gap-2">
99-
{#each SCROLL_BEHAVIORS as b (b.value)}
100-
<button
101-
onclick={() => b.value === "smooth" ? onReset("--sf-scroll-behavior") : onSet("--sf-scroll-behavior", b.value)}
102-
class={`flex-1 py-2 rounded-lg text-[10px] border transition-all cursor-pointer ${
103-
scrollBehavior === b.value
104-
? "bg-indigo-500/15 border-indigo-500/40 text-indigo-800 dark:text-indigo-200"
105-
: "border-black/8 dark:border-white/8 text-slate-600 dark:text-slate-400 hover:bg-black/5 dark:hover:bg-white/5 hover:text-slate-800 dark:hover:text-slate-200"
106-
}`}
107-
>
108-
{b.label}
109-
</button>
110-
{/each}
111-
</div>
112-
</Section>
113-
114-
<div class="h-px bg-black/6 dark:bg-white/6"></div>
115-
11689
<!-- Z-INDEX -->
11790
<Section title="Z-index layers" bind:open={showZIndex}>
11891
<SliderRow

configurator/src/components/panels/MotionPanel.svelte

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,10 @@
1010
// variant support), so it's derived from the chrome theme directly.
1111
let optionBg = $derived(themeState.value === 'dark' ? '#16161e' : '#ffffff');
1212
13-
let { overrides, onSet, onReset, onBulkChange }: {
13+
let { overrides, onSet, onReset }: {
1414
overrides: Record<string, string>;
1515
onSet: (name: string, value: string) => void;
1616
onReset: (name: string) => void;
17-
onBulkChange: (patch: Record<string, string | null>) => void;
1817
} = $props();
1918
2019
const DURATIONS = [
@@ -36,18 +35,25 @@
3635
{ label: "Overshoot", token: "--sf-ease-overshoot", value: "linear(0, 0.6 30%, 1.08 55%, 0.98 75%, 1)", preview: "M0,40 C8,40 20,-10 40,0" },
3736
];
3837
39-
const STAGGER_TOKENS = ["--sf-animation-delay-1","--sf-animation-delay-2","--sf-animation-delay-3","--sf-animation-delay-4","--sf-animation-delay-5"];
38+
// The five fixed per-index stagger delay tokens were removed when
39+
// .sf-stagger landed; the whole sequence is now one knob, and
40+
// core/motion.css multiplies it by the child index and --sf-motion-scale.
41+
const STAGGER_TOKEN = "--sf-stagger-step";
42+
const STAGGER_DEFAULT_MS = 75;
4043
4144
const knobs = KNOBS_BY_DOMAIN["motion"] ?? [];
4245
4346
let scale = $derived((() => { const v = parseFloat(overrides["--sf-motion-scale"] ?? "1"); return isFinite(v) ? v : 1; })());
4447
let motionDisabled = $derived(overrides["--sf-motion-scale"] === "0");
4548
let themeTransition = $derived((() => { const v = parseFloat(overrides["--sf-theme-transition-duration"]?.replace("ms","") ?? String(300 * scale)); return isFinite(v) ? v : Math.round(300 * scale); })());
46-
let staggerBase = $derived.by(() => {
47-
const raw = overrides[STAGGER_TOKENS[0]];
48-
if (raw) return parseFloat(raw.replace("ms",""));
49-
return 75 * scale;
49+
// The stored knob is the un-scaled step; the preview below shows the
50+
// effective delay, so --sf-motion-scale is applied for display only.
51+
let staggerStep = $derived.by(() => {
52+
const raw = overrides[STAGGER_TOKEN];
53+
const v = raw ? parseFloat(raw.replace("ms", "")) : NaN;
54+
return isFinite(v) ? v : STAGGER_DEFAULT_MS;
5055
});
56+
let staggerOverridden = $derived(STAGGER_TOKEN in overrides);
5157
5258
// Animation demo — user picks which easing + duration to feel.
5359
let animating = $state(false);
@@ -85,16 +91,12 @@
8591
}, dur);
8692
}
8793
88-
function setStaggerBase(baseMs: number) {
89-
const patch: Record<string, string> = {};
90-
for (let i = 1; i <= 5; i++) patch[`--sf-animation-delay-${i}`] = `${Math.round(baseMs * i)}ms`;
91-
onBulkChange(patch);
94+
function setStaggerStep(ms: number) {
95+
onSet(STAGGER_TOKEN, `${Math.round(ms)}ms`);
9296
}
9397
9498
function resetStagger() {
95-
const patch: Record<string, null> = {};
96-
for (let i = 1; i <= 5; i++) patch[`--sf-animation-delay-${i}`] = null;
97-
onBulkChange(patch);
99+
onReset(STAGGER_TOKEN);
98100
}
99101
</script>
100102

@@ -252,27 +254,28 @@
252254
<!-- STAGGER -->
253255
<Section title="Stagger" bind:open={showStagger}>
254256
<p class="text-[10px] text-slate-400 dark:text-slate-600 leading-relaxed">
255-
One slider sets all five stagger delays (delay-1 through delay-5 are multiples of this base).
257+
Put <code class="text-slate-600 dark:text-slate-400">.sf-stagger</code> on a parent and each child's
258+
entrance is delayed by its index × this step × the motion scale. One knob retunes the whole sequence.
256259
</p>
257260
<div class="group">
258261
<div class="flex items-center justify-between mb-1.5">
259-
<span class="text-[11px] font-semibold text-slate-800 dark:text-slate-200">Stagger base</span>
260-
{#if STAGGER_TOKENS.some(t => t in overrides)}
262+
<span class="text-[11px] font-semibold text-slate-800 dark:text-slate-200">Stagger step</span>
263+
{#if staggerOverridden}
261264
<button onclick={resetStagger} class="text-[9px] text-slate-500 hover:text-rose-600 dark:hover:text-rose-400 cursor-pointer ">reset</button>
262265
{/if}
263266
</div>
264267
<SliderRow
265-
label="" value={Math.round(staggerBase)} min={0} max={200} step={5} unit="ms"
266-
help="Base unit for --sf-animation-delay-1 through -5"
267-
overridden={STAGGER_TOKENS.some(t => t in overrides)}
268-
onChange={(v) => setStaggerBase(v)}
268+
label="" value={Math.round(staggerStep)} min={0} max={200} step={5} unit="ms"
269+
help="--sf-stagger-step — per-child delay unit for .sf-stagger"
270+
overridden={staggerOverridden}
271+
onChange={(v) => setStaggerStep(v)}
269272
onReset={resetStagger}
270273
/>
271274
</div>
272275
<div class="bg-black/4 dark:bg-white/4 rounded-xl border border-black/8 dark:border-white/8 p-3 space-y-1">
273276
{#each [1,2,3,4,5] as n (n)}
274-
{@const delayMs = Math.round(staggerBase * n)}
275-
{@const maxStaggerDelay = Math.round(staggerBase * 5)}
277+
{@const delayMs = Math.round(staggerStep * scale * n)}
278+
{@const maxStaggerDelay = Math.round(staggerStep * scale * 5)}
276279
<div class="flex items-center gap-2">
277280
<span class="text-[9px] font-mono text-slate-400 dark:text-slate-600 w-6">–{n}</span>
278281
<div class="flex-1 h-1.5 bg-black/8 dark:bg-white/8 rounded-full">

configurator/src/lib/preview/sections.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export function color(): string {
2929
9,
3030
...GRADS.map((g) => specimen(`--sf-gradient-${g}`, `<div class="pv-grad pv-grad--${g}"></div>`)),
3131
);
32-
const surfaceTokens = tokensMatching("--sf-color-surface", "--sf-color-canvas", "--sf-color-inset", "--sf-color-raised")
32+
const surfaceTokens = tokensMatching("--sf-color-surface", "--sf-color-inset", "--sf-color-raised")
3333
.map((t) => t.name);
3434
const surfaces = grid(
3535
10,
@@ -118,7 +118,7 @@ export function type(): string {
118118
const leading = well(`<div class="sf-cluster sf-cluster--m">
119119
<p style="line-height:var(--sf-leading-tight);max-inline-size:12rem">Tight leading — --sf-leading-tight. Two or three lines of copy to show the rhythm.</p>
120120
<p style="line-height:var(--sf-leading-normal);max-inline-size:12rem">Normal leading — --sf-leading-normal. Two or three lines of copy to show the rhythm.</p>
121-
<p style="line-height:var(--sf-leading-loose);max-inline-size:12rem">Loose leading — --sf-leading-loose. Two or three lines of copy to show the rhythm.</p>
121+
<p style="line-height:var(--sf-leading-relaxed);max-inline-size:12rem">Relaxed leading — --sf-leading-relaxed. Two or three lines of copy to show the rhythm.</p>
122122
</div>`);
123123
return page(
124124
"Typography",

0 commit comments

Comments
 (0)