diff --git a/configurator/src/components/inputs/ValueField.svelte b/configurator/src/components/inputs/ValueField.svelte index 7e3d81bc..d94c8267 100644 --- a/configurator/src/components/inputs/ValueField.svelte +++ b/configurator/src/components/inputs/ValueField.svelte @@ -22,10 +22,17 @@ let draft = $state(""); let editing = $state(false); let cancelling = $state(false); - // Reset a user-selected tab when another surface changes this token. + // Switching back to Inherit throws away the override. The tab sits right next + // to Value/Expression and reads like a harmless view switch, so a stray click + // used to silently wipe an edit. When there's an actual override to lose we + // arm this confirm step instead of resetting immediately. + let confirmingInherit = $state(false); + // Reset a user-selected tab (and any pending confirm) when another surface + // changes this token. $effect(() => { overrideValue; manualMode = null; + confirmingInherit = false; }); // Seed the text field from the live value whenever we're not mid-edit. $effect(() => { @@ -41,8 +48,22 @@ } function setMode(m: ValueMode) { + if (m === "inherit") { + // Nothing overridden → already inheriting, so this is a no-op, not a + // destructive reset; just settle on auto-detect. + if (overrideValue === undefined) { manualMode = null; confirmingInherit = false; return; } + // Otherwise require an explicit confirmation before discarding the value. + confirmingInherit = true; + return; + } + confirmingInherit = false; manualMode = m; - if (m === "inherit") { onReset(); manualMode = null; } + } + + function confirmInherit() { + confirmingInherit = false; + manualMode = null; + onReset(); } const TABS: { id: ValueMode; label: string }[] = [ @@ -56,11 +77,12 @@
{#each TABS as t (t.id)} + {@const active = confirmingInherit ? t.id === "inherit" : mode === t.id}
+ + {#if confirmingInherit} +
+ + Discard this override and inherit {token.value}? + + + +
+ {/if} + {#if mode === "inherit"}
default: {token.value} diff --git a/configurator/src/components/panels/BordersPanel.svelte b/configurator/src/components/panels/BordersPanel.svelte index d7b3e6ec..9daa63d3 100644 --- a/configurator/src/components/panels/BordersPanel.svelte +++ b/configurator/src/components/panels/BordersPanel.svelte @@ -224,6 +224,14 @@ currentRaw={overrides["--sf-divider-gap"]} onRawSet={(v) => onSet("--sf-divider-gap", v)} /> + + +
+

Content above

+
+

Content below

+
@@ -348,6 +356,18 @@ onRawSet={(v) => onSet(t.token, v)} /> {/each} + + +
+ +
{/if} diff --git a/configurator/src/components/panels/EffectsPanel.svelte b/configurator/src/components/panels/EffectsPanel.svelte index 808b867d..ec55de5c 100644 --- a/configurator/src/components/panels/EffectsPanel.svelte +++ b/configurator/src/components/panels/EffectsPanel.svelte @@ -155,6 +155,20 @@ {/each} + + +
+ {#each TEXT_SHADOW_TOKENS as t (t.token)} +
+ Aa + {t.token.replace("--sf-text-shadow-", "")} +
+ {/each} +
diff --git a/configurator/src/components/panels/LayoutPanel.svelte b/configurator/src/components/panels/LayoutPanel.svelte index 86b5ab91..b19b41aa 100644 --- a/configurator/src/components/panels/LayoutPanel.svelte +++ b/configurator/src/components/panels/LayoutPanel.svelte @@ -445,6 +445,18 @@ {/if} {/each} + +
+
+ {#each [1.75, 1, 2.25, 1.25] as h, i (i)} + {i + 1} + {/each} +
+
@@ -492,6 +504,13 @@ onReset={() => onReset("--sf-equal-rule-color")} /> + +
+
+

SLASHED flows this text across as many equal columns as fit the box, divided by the column rule. Lower the min column width to pack in more, narrower columns; raise it for fewer, roomier ones. The rule width, style and colour draw the divider.

+
+
@@ -549,6 +568,18 @@ {/if} + +
+
+ {#each [1, 2, 3, 4, 5, 6] as n (n)} +
{n}
+ {/each} +
+
diff --git a/configurator/src/components/panels/MiscPanel.svelte b/configurator/src/components/panels/MiscPanel.svelte index f03008a2..af9e48e8 100644 --- a/configurator/src/components/panels/MiscPanel.svelte +++ b/configurator/src/components/panels/MiscPanel.svelte @@ -53,6 +53,24 @@ function getSizeValue(t: typeof SIZE_TOKENS[0]): number { return parseNum(overrides[t.token]?.replace("rem",""), t.default); } + + const ICON_STEPS = ["xs", "s", "m", "l", "xl", "2xl"]; + + // A deliberately landscape (2:1) sample with a centered ring and a full-bleed + // border, so object-fit differences are unmistakable: cover crops the sides, + // contain letterboxes, fill distorts the circle, none overflows at native px. + const OBJECT_FIT_IMG = `data:image/svg+xml,${encodeURIComponent( + ``, + )}`; + + // Layering ladder for the preview: ordered by each rung's *current* value + // (override or default), highest first, so reordering the numbers reorders + // the visual stack instead of showing a fixed hierarchy. + let zLadder = $derived( + Z_INDEX_STEPS + .map((z) => ({ ...z, val: parseNum(overrides[z.token], z.def) })) + .sort((a, b) => b.val - a.val), + );
@@ -96,6 +114,24 @@ /> {/each}
+ + +
+
Higher rungs paint above lower ones.
+
+ {#each zLadder as z, i (z.token)} +
+ {z.label} + {z.val} +
+ {/each} +
+
@@ -310,6 +346,19 @@ onChange={(v) => onSet("--sf-icon-box-pad", `${v}em`)} onReset={() => onReset("--sf-icon-box-pad")} /> + + +
+ {#each ICON_STEPS as s (s)} +
+ + {s} +
+ {/each} +
@@ -350,6 +399,22 @@ {/if} + + +
+
+ Object-fit sample +
+
+ object-fit: {overrides["--sf-object-fit"] ?? "cover"} +
+
@@ -386,6 +451,9 @@ {/each} +

+ No preview — safe-area insets resolve to the physical device (notch / home indicator) at runtime and are 0 on desktop. +

@@ -408,6 +476,20 @@ {/if} + + +
+ +
diff --git a/configurator/src/components/panels/TypographyPanel.svelte b/configurator/src/components/panels/TypographyPanel.svelte index b2f27872..ced8be1e 100644 --- a/configurator/src/components/panels/TypographyPanel.svelte +++ b/configurator/src/components/panels/TypographyPanel.svelte @@ -367,6 +367,16 @@ {/each} + +
+
+ 1,204.05 + 98.10 + 13,760.75 +
+
Optical sizing
@@ -561,6 +571,19 @@
+ +
+ {#each LEADING_TOKENS as t (t.token)} +
+ {t.label} +

+ The quick brown fox jumps over the lazy dog while the rhythm of these lines shifts with the leading. +

+
+ {/each} +
+ {/each} + + +
+ {#each TRACKING_TOKENS as t (t.token)} +
+ {t.label} + Typography +
+ {/each} +