diff --git a/configurator/src/components/DomainPanel.svelte b/configurator/src/components/DomainPanel.svelte
index 470d6176..89c8b55e 100644
--- a/configurator/src/components/DomainPanel.svelte
+++ b/configurator/src/components/DomainPanel.svelte
@@ -87,7 +87,7 @@
{:else if domain === "shadows"}
{:else if domain === "motion"}
-
+
{:else if domain === "effects"}
{:else if domain === "macros"}
diff --git a/configurator/src/components/panels/ColorsPanel.svelte b/configurator/src/components/panels/ColorsPanel.svelte
index df49ab42..492ab7ae 100644
--- a/configurator/src/components/panels/ColorsPanel.svelte
+++ b/configurator/src/components/panels/ColorsPanel.svelte
@@ -57,6 +57,9 @@
{ name: "--sf-gradient-tertiary", label: "Tertiary", group: "brand", kind: "angle", space: "oklch", angle: 135, dir: "right",
stop1: "var(--sf-color-tertiary)", stop2: "oklch(from var(--sf-color-tertiary) calc(l - 0.08) c h)",
formula: "linear-gradient(in oklch 135deg, var(--sf-color-tertiary), oklch(from var(--sf-color-tertiary) calc(l - 0.08) c h))" },
+ { name: "--sf-gradient-action", label: "Action", group: "brand", kind: "angle", space: "oklch", angle: 135, dir: "right",
+ stop1: "var(--sf-color-action)", stop2: "oklch(from var(--sf-color-action) calc(l - 0.08) c h)",
+ formula: "linear-gradient(in oklch 135deg, var(--sf-color-action), oklch(from var(--sf-color-action) calc(l - 0.08) c h))" },
{ name: "--sf-gradient-brand", label: "Brand", group: "brand", kind: "angle", space: "oklch", angle: 135, dir: "right",
stop1: "var(--sf-color-primary)", stop2: "oklch(from var(--sf-color-primary) l c calc(h + 30))",
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 @@
{ name: "--sf-color-info-source-light", label: "Info", side: "light", default: "oklch(0.48 0.18 235)", colorKey: "info" },
{ name: "--sf-color-info-source-dark", label: "Info", side: "dark", default: "oklch(0.71 0.162 235)", colorKey: "info" },
{ name: "--sf-color-danger-source-light", label: "Danger", side: "light", default: "oklch(0.48 0.22 12)", colorKey: "danger" },
- { name: "--sf-color-danger-source-dark", label: "Danger", side: "dark", default: "oklch(0.73 0.198 12)", colorKey: "danger" },
+ { name: "--sf-color-danger-source-dark", label: "Danger", side: "dark", default: "oklch(0.71 0.198 12)", colorKey: "danger" },
];
// Baked per-step ramp curve — mirrors core/tokens.css: how far each step
@@ -178,11 +181,13 @@
const PALETTE_COLOR_KEYS = [...BRAND_COLOR_KEYS, "base"];
// Status families (success/warning/info/danger) have NO numeric 50-950
- // ramp in the framework — only these four derived values actually exist
- // (core/tokens.css: resolved color + -subtle/-muted alpha washes + a
- // light-dark() -strong shift). Mirror that here instead of faking a ramp.
+ // ramp in the framework — only these five derived values actually exist
+ // (core/tokens.css: resolved color + -tint/-subtle/-muted alpha washes at
+ // 0.05/0.12/0.3 + a light-dark() -strong shift). Mirror that here instead of
+ // faking a ramp.
const STATUS_VARIANTS: { label: string; expr: (key: string) => string }[] = [
{ label: "Base", expr: (k) => `var(--sf-color-${k})` },
+ { label: "Tint", expr: (k) => `var(--sf-color-${k}-tint)` },
{ label: "Subtle", expr: (k) => `var(--sf-color-${k}-subtle)` },
{ label: "Muted", expr: (k) => `var(--sf-color-${k}-muted)` },
{ label: "Strong", expr: (k) => `var(--sf-color-${k}-strong)` },
diff --git a/configurator/src/components/panels/MiscPanel.svelte b/configurator/src/components/panels/MiscPanel.svelte
index 0ad67968..2f78136b 100644
--- a/configurator/src/components/panels/MiscPanel.svelte
+++ b/configurator/src/components/panels/MiscPanel.svelte
@@ -23,11 +23,6 @@
{ label: "Tooltip", token: "--sf-z-tooltip", note: "Inline tooltips", def: 1060 },
];
- const SCROLL_BEHAVIORS = [
- { label: "Smooth", value: "smooth" },
- { label: "Auto", value: "auto" },
- ];
-
const SIZE_TOKENS = [
{ label: "XS", token: "--sf-size-xs", default: 1.5 },
{ label: "S", token: "--sf-size-s", default: 2 },
@@ -43,14 +38,12 @@
}
let touchTarget = $derived(parseNum(overrides["--sf-touch-target"], 44, "px"));
- let scrollBehavior = $derived(overrides["--sf-scroll-behavior"] ?? "smooth");
let zBaseOffset = $derived(parseNum(overrides["--sf-z-base"], 0));
let caretColor = $derived(overrides["--sf-caret-color"] ?? "");
let underlineOffset = $derived(parseNum(overrides["--sf-link-underline-offset"]?.replace("em",""), 0.15));
let underlineThickness = $derived(overrides["--sf-link-underline-thickness"] ?? "auto");
let showTouchTarget = $state(false);
- let showScrollBehavior = $state(false);
let showZIndex = $state(false);
let showTextSelection = $state(false);
let showComponentSizes = $state(false);
@@ -93,26 +86,6 @@
-
-
-
- {#each SCROLL_BEHAVIORS as b (b.value)}
-
- {/each}
-
-
-
-
-
;
onSet: (name: string, value: string) => void;
onReset: (name: string) => void;
- onBulkChange: (patch: Record) => void;
} = $props();
const DURATIONS = [
@@ -36,18 +35,25 @@
{ 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" },
];
- const STAGGER_TOKENS = ["--sf-animation-delay-1","--sf-animation-delay-2","--sf-animation-delay-3","--sf-animation-delay-4","--sf-animation-delay-5"];
+ // The five fixed per-index stagger delay tokens were removed when
+ // .sf-stagger landed; the whole sequence is now one knob, and
+ // core/motion.css multiplies it by the child index and --sf-motion-scale.
+ const STAGGER_TOKEN = "--sf-stagger-step";
+ const STAGGER_DEFAULT_MS = 75;
const knobs = KNOBS_BY_DOMAIN["motion"] ?? [];
let scale = $derived((() => { const v = parseFloat(overrides["--sf-motion-scale"] ?? "1"); return isFinite(v) ? v : 1; })());
let motionDisabled = $derived(overrides["--sf-motion-scale"] === "0");
let themeTransition = $derived((() => { const v = parseFloat(overrides["--sf-theme-transition-duration"]?.replace("ms","") ?? String(300 * scale)); return isFinite(v) ? v : Math.round(300 * scale); })());
- let staggerBase = $derived.by(() => {
- const raw = overrides[STAGGER_TOKENS[0]];
- if (raw) return parseFloat(raw.replace("ms",""));
- return 75 * scale;
+ // The stored knob is the un-scaled step; the preview below shows the
+ // effective delay, so --sf-motion-scale is applied for display only.
+ let staggerStep = $derived.by(() => {
+ const raw = overrides[STAGGER_TOKEN];
+ const v = raw ? parseFloat(raw.replace("ms", "")) : NaN;
+ return isFinite(v) ? v : STAGGER_DEFAULT_MS;
});
+ let staggerOverridden = $derived(STAGGER_TOKEN in overrides);
// Animation demo — user picks which easing + duration to feel.
let animating = $state(false);
@@ -85,16 +91,12 @@
}, dur);
}
- function setStaggerBase(baseMs: number) {
- const patch: Record = {};
- for (let i = 1; i <= 5; i++) patch[`--sf-animation-delay-${i}`] = `${Math.round(baseMs * i)}ms`;
- onBulkChange(patch);
+ function setStaggerStep(ms: number) {
+ onSet(STAGGER_TOKEN, `${Math.round(ms)}ms`);
}
function resetStagger() {
- const patch: Record = {};
- for (let i = 1; i <= 5; i++) patch[`--sf-animation-delay-${i}`] = null;
- onBulkChange(patch);
+ onReset(STAGGER_TOKEN);
}
@@ -252,27 +254,28 @@
- One slider sets all five stagger delays (delay-1 through delay-5 are multiples of this base).
+ Put .sf-stagger on a parent and each child's
+ entrance is delayed by its index × this step × the motion scale. One knob retunes the whole sequence.
- Stagger base
- {#if STAGGER_TOKENS.some(t => t in overrides)}
+ Stagger step
+ {#if staggerOverridden}
{/if}
t in overrides)}
- onChange={(v) => setStaggerBase(v)}
+ label="" value={Math.round(staggerStep)} min={0} max={200} step={5} unit="ms"
+ help="--sf-stagger-step — per-child delay unit for .sf-stagger"
+ overridden={staggerOverridden}
+ onChange={(v) => setStaggerStep(v)}
onReset={resetStagger}
/>