From 51769634de60492d55f6991bdc9be299e0bd0ee3 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 18 Jul 2026 14:41:48 +0000 Subject: [PATCH 1/9] feat(configurator): unify text & display typographic scale controls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The sf-text and sf-display-text scales were edited with different inputs, adjustments and previews despite being the same fluid clamp() scale. Make them consistent and simpler to use: - Add a "Scale multiplier" slider to both scales (--sf-text-scale and --sf-text-display-scale) — the display multiplier was consumed by the preview engine but had no control; the text one likewise wasn't editable. - Add the missing Display S line-height; display line-heights are now s/m/l. - Note on the display scale that its modular ratio is shared with the text scale (matching the framework, which reuses --sf-text-ratio-*). - Give the display scale a per-step ramp preview alongside the text ramp in Scale preview (previously only text had one). - Extract a shared weight-grid snippet, removing four duplicated markup blocks. Configurator-only; no framework tokens changed. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_013BRVgKfEYocPCHz9KU96FN --- .../components/panels/TypographyPanel.svelte | 153 ++++++++++-------- 1 file changed, 87 insertions(+), 66 deletions(-) diff --git a/configurator/src/components/panels/TypographyPanel.svelte b/configurator/src/components/panels/TypographyPanel.svelte index f8e0690f9..d04e70e50 100644 --- a/configurator/src/components/panels/TypographyPanel.svelte +++ b/configurator/src/components/panels/TypographyPanel.svelte @@ -160,8 +160,9 @@ let baseMax = $derived(num("--sf-text-base-max", 1.25)); let dispMin = $derived(num("--sf-text-display-base-min", 2.4)); let dispMax = $derived(num("--sf-text-display-base-max", 3)); - let taper = $derived(num("--sf-leading-taper", 0)); - let textScale = $derived(num("--sf-text-scale", 1)); + let taper = $derived(num("--sf-leading-taper", 0)); + let textScale = $derived(num("--sf-text-scale", 1)); + let displayScale = $derived(num("--sf-text-display-scale", 1)); // Shared fluid viewport endpoints (rem, unitless). Min = mobile, max = desktop. let vwMin = $derived(num("--sf-fluid-min-vw", 22.5)); let vwMax = $derived(num("--sf-fluid-max-vw", 90)); @@ -251,6 +252,34 @@ }); + +{#snippet weightGrid(label: string, tokenName: string, defaultVal: string)} + {@const current = overrides[tokenName] ?? defaultVal} + {@const isOverridden = tokenName in overrides} +
+
+ {label} weight + {#if isOverridden} + + {/if} +
+
+ {#each WEIGHT_OPTIONS as w (w)} + + {/each} +
+
+{/snippet} +
@@ -495,35 +524,8 @@ {#if showBodyText} - {#each [ - { label: "Body strong", tokenName: "--sf-font-weight-strong" }, - { label: "Interactive", tokenName: "--sf-font-weight-interactive" }, - ] as row (row.tokenName)} - {@const defaultVal = WEIGHT_DEFAULTS[row.tokenName] ?? "600"} - {@const current = overrides[row.tokenName] ?? defaultVal} - {@const isOverridden = row.tokenName in overrides} -
-
- {row.label} weight - {#if isOverridden} - - {/if} -
-
- {#each WEIGHT_OPTIONS as w (w)} - - {/each} -
-
- {/each} + {@render weightGrid("Body strong", "--sf-font-weight-strong", WEIGHT_DEFAULTS["--sf-font-weight-strong"] ?? "600")} + {@render weightGrid("Interactive", "--sf-font-weight-interactive", WEIGHT_DEFAULTS["--sf-font-weight-interactive"] ?? "600")}
@@ -685,14 +687,29 @@ onMaxChange={(v) => onSet("--sf-text-display-base-max", String(v))} /> - -
+ + onSet("--sf-text-display-scale", String(v))} + onReset={() => onReset("--sf-text-display-scale")} + /> + +

+ Modular ratio is shared with the text scale (Mobile {ratioMin} → Desktop {ratioMax}) — edit it under “Modular scale”. +

+ + +
{#each [ - { label: "Display L line-height", token: "--sf-display-l-line-height", def: 1 }, - { label: "Display M line-height", token: "--sf-display-m-line-height", def: 1.05 }, + { label: "Display S", token: "--sf-display-s-line-height", def: 1.1 }, + { label: "Display M", token: "--sf-display-m-line-height", def: 1.05 }, + { label: "Display L", token: "--sf-display-l-line-height", def: 1 }, ] as row (row.token)}
-
{row.label}
+
{row.label} line-height
- {#each [ - { label: "Display", tokenName: "--sf-font-weight-display" }, - { label: "Heading", tokenName: "--sf-font-weight-heading" }, - ] as row (row.tokenName)} - {@const defaultVal = WEIGHT_DEFAULTS[row.tokenName] ?? "700"} - {@const current = overrides[row.tokenName] ?? defaultVal} - {@const isOverridden = row.tokenName in overrides} -
-
- {row.label} weight - {#if isOverridden} - - {/if} -
-
- {#each WEIGHT_OPTIONS as w (w)} - - {/each} -
-
- {/each} + {@render weightGrid("Display", "--sf-font-weight-display", WEIGHT_DEFAULTS["--sf-font-weight-display"] ?? "700")} + {@render weightGrid("Heading", "--sf-font-weight-heading", WEIGHT_DEFAULTS["--sf-font-weight-heading"] ?? "700")} {/if} @@ -783,6 +773,15 @@ onRatioMaxChange={(v) => onSet("--sf-text-ratio-max", String(v))} /> + + onSet("--sf-text-scale", String(v))} + onReset={() => onReset("--sf-text-scale")} + /> +
Line height scale
@@ -870,9 +869,12 @@ {showScalePreview ? "▲" : "▼"} {#if showScalePreview} + {@const midBase = (baseMin + baseMax) / 2} + {@const midDisp = (dispMin + dispMax) / 2} + {@const midRatio = (ratioMin + ratioMax) / 2}
+
Text
{#each [...TEXT_STEPS].reverse() as { label, factor } (label)} - {@const midBase = (baseMin + baseMax) / 2} {@const size = midBase * factor * textScale}
{label} @@ -885,6 +887,25 @@ {size.toFixed(2)}rem
{/each} + +
Display
+ {#each [ + { label: "l", factor: midRatio * midRatio }, + { label: "m", factor: midRatio }, + { label: "s", factor: 1 }, + ] as { label, factor } (label)} + {@const size = midDisp * factor * displayScale} +
+ {label} + + Aa + + {size.toFixed(2)}rem +
+ {/each}
{/if} From 3fc412c762a608fe98b171e18ff97810064c985a Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 18 Jul 2026 14:42:03 +0000 Subject: [PATCH 2/9] feat(configurator): consistency pass across colors, macros & effects panels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Colors: add a "Copy to dark" action to the brand sources (primary, secondary, tertiary, action). It snapshots the light source's oklch value into the dark source and switches the row to manual — same effect as pasting the same colour into both. Not live-linked. Base/neutral/status are unchanged. - Colors: replace the lone raw gradient-angle control with RangeWithNumber, matching every other angle/hue control. - Macros: route the scrim, prose-marker and surface-bg colour fields through ColorInput (swatch + native picker) instead of plain text inputs. - Effects: remove the duplicated Scrim and Scroll-shadow sections — both edit .sf-scrim / .sf-scroll-shadow macro tokens whose richer editors (with previews and text-shadow) already live in the Macros panel. Configurator-only; no framework tokens changed. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_013BRVgKfEYocPCHz9KU96FN --- .../src/components/panels/ColorsPanel.svelte | 51 +++++++--- .../src/components/panels/EffectsPanel.svelte | 99 ------------------- .../src/components/panels/MacrosPanel.svelte | 84 +++++++++------- 3 files changed, 83 insertions(+), 151 deletions(-) diff --git a/configurator/src/components/panels/ColorsPanel.svelte b/configurator/src/components/panels/ColorsPanel.svelte index aa964e009..557602ba3 100644 --- a/configurator/src/components/panels/ColorsPanel.svelte +++ b/configurator/src/components/panels/ColorsPanel.svelte @@ -7,6 +7,7 @@ import OklchColorDesk from '../inputs/OklchColorDesk.svelte'; import PowerKnobRow from '../inputs/PowerKnobRow.svelte'; import SliderRow from '../inputs/SliderRow.svelte'; + import RangeWithNumber from '../inputs/RangeWithNumber.svelte'; import ColorInput from '../inputs/ColorInput.svelte'; let { tokens, overrides, onSet, onReset, onBulkChange, onSelectDomain }: { @@ -426,6 +427,19 @@ onSet(light.name, newVal); } + // Brand keys that offer a "Copy to dark" action (snapshot the light source + // into the dark source — same effect as pasting the same colour into both). + const COPY_TO_DARK_KEYS = ["primary", "secondary", "tertiary", "action"]; + + // One-shot: copy the light source's current concrete oklch value into the + // dark source token and switch the row to manual. Not live-linked — a later + // edit to light leaves this copied dark value untouched (copy-paste, not a ref). + function copyLightToDark(colorKey: string, dark: ColorSource | undefined, light: ColorSource) { + if (!dark) return; + autoDarkSet = new Set([...autoDarkSet].filter(k => k !== colorKey)); + onSet(dark.name, sourceValue(light)); + } + function toggleDarkMode(colorKey: string, dark: ColorSource | undefined, lightName: string) { const darkOverridden = !!(dark && (dark.name in overrides)); const effectivelyAuto = autoDarkSet.has(colorKey) && !darkOverridden; @@ -529,14 +543,23 @@
{light.label}
{#if dark} - +
+ {#if COPY_TO_DARK_KEYS.includes(light.colorKey)} + + {/if} + +
{/if}
Angle - setGradientPart(g, "angle", parseInt((ev.target as HTMLInputElement).value))} - class="flex-1 accent-indigo-500" - /> - {e.angle}° +
+ setGradientPart(g, "angle", v)} + /> +
{/if} diff --git a/configurator/src/components/panels/EffectsPanel.svelte b/configurator/src/components/panels/EffectsPanel.svelte index d9ca47272..733c4d4dd 100644 --- a/configurator/src/components/panels/EffectsPanel.svelte +++ b/configurator/src/components/panels/EffectsPanel.svelte @@ -8,13 +8,6 @@ onReset: (name: string) => void; } = $props(); - const SCRIM_DIRECTIONS = [ - { label: "To top", value: "to top" }, - { label: "To bottom", value: "to bottom" }, - { label: "To left", value: "to left" }, - { label: "To right", value: "to right" }, - ]; - const TEXT_SHADOW_TOKENS = [ { label: "Extra small", token: "--sf-text-shadow-xs", default: "0 0.5px 1px oklch(…)" }, { label: "Small", token: "--sf-text-shadow-s", default: "0 1px 2px oklch(…)" }, @@ -34,18 +27,13 @@ let blur = $derived(parseNum(overrides["--sf-blur"], 12, "px")); let opacityMuted = $derived(parseNum(overrides["--sf-opacity-muted"], 0.5)); let opacityDisabled = $derived(parseNum(overrides["--sf-opacity-disabled"], 0.45)); - let scrimDir = $derived(overrides["--sf-scrim-direction"] ?? "to top"); - let scrimColor = $derived(overrides["--sf-scrim-color"] ?? ""); - let scrollShadowSize = $derived(parseNum(overrides["--sf-scroll-shadow-size"]?.replace("rem",""), 2)); let pendingOpacity = $derived(parseNum(overrides["--sf-state-pending-opacity"], 0.7)); let scrollbarThumb = $derived(overrides["--sf-scrollbar-thumb"] ?? ""); let scrollbarTrack = $derived(overrides["--sf-scrollbar-track"] ?? ""); let showBlur = $state(false); let showOpacity = $state(false); - let showScrim = $state(false); let showScrollbar = $state(false); - let showScrollShadow = $state(false); let showTextShadow = $state(false); let showDropShadow = $state(false); @@ -140,70 +128,6 @@
- -
- - {#if showScrim} -

- Gradient overlay for hero images and media content. Used by the .sf-scrim macro. -

- - -
-
Color
- onSet("--sf-scrim-color", v)} - onReset={() => onReset("--sf-scrim-color")} - /> -
- -
-
Direction
-
- {#each SCRIM_DIRECTIONS as d (d.value)} - - {/each} -
-
- - -
-
-
-
Scrim preview
-
-
- {/if} -
- -
-
- -
- - {#if showScrollShadow} - onSet("--sf-scroll-shadow-size", `${v}rem`)} - onReset={() => onReset("--sf-scroll-shadow-size")} - /> - {/if} -
- -
-
- {/if} +
+ onSet("--sf-scrim-color", v)} + onReset={() => onReset("--sf-scrim-color")} + /> +
Direction
@@ -352,19 +350,16 @@ />
Marker color
- { - const v = (e.target as HTMLInputElement).value.trim(); - v ? onSet("--sf-prose-marker-color", v) : onReset("--sf-prose-marker-color"); - }} - class="flex-1 min-w-0 bg-black/5 dark:bg-white/5 border border-black/10 dark:border-white/10 rounded px-1.5 py-1 text-[9px] font-mono text-slate-700 dark:text-slate-300 placeholder:text-slate-600 focus:outline-none focus:border-indigo-500" - /> - {#if "--sf-prose-marker-color" in overrides} - - {/if} +
+ onSet("--sf-prose-marker-color", v)} + onReset={() => onReset("--sf-prose-marker-color")} + /> +
{/if} @@ -424,18 +419,31 @@ {#each SURFACE_BG_TEXT as t (t.token)}
{t.label}
- { - const v = (e.target as HTMLInputElement).value; - v.trim() ? onSet(t.token, v) : onReset(t.token); - }} - class="flex-1 min-w-0 bg-black/5 dark:bg-white/5 border border-black/10 dark:border-white/10 rounded px-1.5 py-1 text-[9px] font-mono text-slate-700 dark:text-slate-300 placeholder:text-slate-600 focus:outline-none focus:border-indigo-500" - /> - {#if t.token in overrides} - + {#if t.token === "--sf-surface-bg-color"} +
+ onSet(t.token, v)} + onReset={() => onReset(t.token)} + /> +
+ {:else} + { + const v = (e.target as HTMLInputElement).value; + v.trim() ? onSet(t.token, v) : onReset(t.token); + }} + class="flex-1 min-w-0 bg-black/5 dark:bg-white/5 border border-black/10 dark:border-white/10 rounded px-1.5 py-1 text-[9px] font-mono text-slate-700 dark:text-slate-300 placeholder:text-slate-600 focus:outline-none focus:border-indigo-500" + /> + {#if t.token in overrides} + + {/if} {/if}
{/each} From 6d3831e9d649ee0d9c8e8245b6d36fab38d12cec Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 18 Jul 2026 14:55:21 +0000 Subject: [PATCH 3/9] refactor(configurator): shared Toggle, AspectRatioInput & RawTokenRow; z-index sliders Extract three reusable inputs to remove duplicated markup and unify controls that did the same thing differently across panels: - Toggle: the pill switch, previously hand-rolled in Shadows (glow), Motion (disable motion) and Misc (state flags). Two sizes. - AspectRatioInput: one preset grid for "pick a raw aspect ratio", used by Macros --sf-aspect (with preview) and Layout --sf-frame-ratio. - RawTokenRow: the "free-text token value + inline reset" row, used by Layout named ratios, Macros scrim text-shadow and the surface-bg image/overlay/ animation fields. Also give the Misc z-index tokens real per-step sliders (seeded from the framework defaults) instead of a read-only list that punted to the All-tokens tab, matching how every other numeric ladder is edited. Drops the phantom --sf-z-popover entry (no such framework token). Configurator-only; no framework tokens changed. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_013BRVgKfEYocPCHz9KU96FN --- .../components/inputs/AspectRatioInput.svelte | 49 +++++++++++++ .../src/components/inputs/RawTokenRow.svelte | 34 +++++++++ .../src/components/inputs/Toggle.svelte | 29 ++++++++ .../src/components/panels/LayoutPanel.svelte | 42 ++++------- .../src/components/panels/MacrosPanel.svelte | 70 ++++++------------- .../src/components/panels/MiscPanel.svelte | 52 +++++++------- .../src/components/panels/MotionPanel.svelte | 18 ++--- .../src/components/panels/ShadowsPanel.svelte | 20 ++---- 8 files changed, 184 insertions(+), 130 deletions(-) create mode 100644 configurator/src/components/inputs/AspectRatioInput.svelte create mode 100644 configurator/src/components/inputs/RawTokenRow.svelte create mode 100644 configurator/src/components/inputs/Toggle.svelte diff --git a/configurator/src/components/inputs/AspectRatioInput.svelte b/configurator/src/components/inputs/AspectRatioInput.svelte new file mode 100644 index 000000000..6ab5d4748 --- /dev/null +++ b/configurator/src/components/inputs/AspectRatioInput.svelte @@ -0,0 +1,49 @@ + + +
+ {#each items as p (p.value)} + + {/each} +
+ +{#if showPreview} +
+
{value}
+
+{/if} diff --git a/configurator/src/components/inputs/RawTokenRow.svelte b/configurator/src/components/inputs/RawTokenRow.svelte new file mode 100644 index 000000000..7550f5d6c --- /dev/null +++ b/configurator/src/components/inputs/RawTokenRow.svelte @@ -0,0 +1,34 @@ + + +
+ {#if label} + {label} + {/if} + { const v = (e.target as HTMLInputElement).value; v.trim() ? onSet(v) : onReset(); }} + class="flex-1 min-w-0 bg-black/5 dark:bg-white/5 border border-black/10 dark:border-white/10 rounded px-1.5 py-1 text-[9px] font-mono text-slate-700 dark:text-slate-300 placeholder:text-slate-600 focus:outline-none focus:border-indigo-500" + /> + {#if overridden} + + {/if} +
diff --git a/configurator/src/components/inputs/Toggle.svelte b/configurator/src/components/inputs/Toggle.svelte new file mode 100644 index 000000000..82a6a4588 --- /dev/null +++ b/configurator/src/components/inputs/Toggle.svelte @@ -0,0 +1,29 @@ + + + diff --git a/configurator/src/components/panels/LayoutPanel.svelte b/configurator/src/components/panels/LayoutPanel.svelte index 94cfd1a04..ae0c6f105 100644 --- a/configurator/src/components/panels/LayoutPanel.svelte +++ b/configurator/src/components/panels/LayoutPanel.svelte @@ -2,6 +2,8 @@ import type { SlashedToken } from '../../types'; import SliderRow from '../inputs/SliderRow.svelte'; import ColorInput from '../inputs/ColorInput.svelte'; + import AspectRatioInput from '../inputs/AspectRatioInput.svelte'; + import RawTokenRow from '../inputs/RawTokenRow.svelte'; import { themeState } from '../../lib/theme.svelte'; import { SPACE_SCALE, CONTAINER_SCALE } from '../../lib/variableScales'; @@ -556,18 +558,11 @@
Frame ratio

--sf-frame-ratio — aspect ratio for .sf-frame

-
- {#each FRAME_PRESETS as r (r)} - - {/each} -
+
@@ -690,22 +685,13 @@ { label: "Cinema", token: "--sf-ratio-cinema", def: "21 / 9" }, { label: "Golden", token: "--sf-ratio-golden", def: "1.618 / 1" }, ] as r (r.token)} -
- {r.label} - { - const v = (e.target as HTMLInputElement).value.trim(); - v ? onSet(r.token, v) : onReset(r.token); - }} - class="flex-1 min-w-0 bg-black/5 dark:bg-white/5 border border-black/10 dark:border-white/10 rounded px-1.5 py-1 text-[9px] font-mono text-slate-700 dark:text-slate-300 placeholder:text-slate-600 focus:outline-none focus:border-indigo-500" - /> - {#if r.token in overrides} - - {/if} -
+ onSet(r.token, v)} + onReset={() => onReset(r.token)} + /> {/each}
{/if} diff --git a/configurator/src/components/panels/MacrosPanel.svelte b/configurator/src/components/panels/MacrosPanel.svelte index b72405d09..8f7577853 100644 --- a/configurator/src/components/panels/MacrosPanel.svelte +++ b/configurator/src/components/panels/MacrosPanel.svelte @@ -1,6 +1,8 @@ + +
+ + {#if open} + {@render children()} + {/if} +
diff --git a/configurator/src/components/panels/BordersPanel.svelte b/configurator/src/components/panels/BordersPanel.svelte index f018e8d88..acb20af22 100644 --- a/configurator/src/components/panels/BordersPanel.svelte +++ b/configurator/src/components/panels/BordersPanel.svelte @@ -3,6 +3,7 @@ import PowerKnobRow from '../inputs/PowerKnobRow.svelte'; import SliderRow from '../inputs/SliderRow.svelte'; import ColorInput from '../inputs/ColorInput.svelte'; + import Section from '../inputs/Section.svelte'; import { SPACE_SCALE, RADIUS_SCALE, BORDER_WIDTH_SCALE, type VarOption } from '../../lib/variableScales'; let { overrides, onSet, onReset }: { @@ -85,16 +86,7 @@
-
- - {#if showBorderColor} +
Drives --sf-color-border--strong, --subtle, --translucent automatically.

- {/if} -
+
-
- - {#if showBorderWidths} +
{/each}
- {/if} - +
-
- - {#if showLineStyles} +
{#each [ { label: "Border", token: "--sf-border-style", default: "solid" }, @@ -212,22 +184,12 @@
{(1 * borderScale).toFixed(1)}px · {borderStyle}
- {/if} - +
-
- - {#if showDividers} +
Color
onSet("--sf-divider-gap", v)} /> - {/if} -
+
-
- - {#if showFocusRing} +
- {/if} - +
@@ -383,16 +334,7 @@
-
- - {#if showMediaRadius} +

--sf-media-radius — 0 by default (off). Rounds every <img>/<figure> globally via a zero-specificity :where() rule; .sf-bg-layer and component-level radii still win. @@ -414,8 +356,7 @@ style={`border-radius: ${mediaRadius}rem`} > - {/if} -

+
diff --git a/configurator/src/components/panels/ColorsPanel.svelte b/configurator/src/components/panels/ColorsPanel.svelte index 557602ba3..326777921 100644 --- a/configurator/src/components/panels/ColorsPanel.svelte +++ b/configurator/src/components/panels/ColorsPanel.svelte @@ -9,6 +9,7 @@ import SliderRow from '../inputs/SliderRow.svelte'; import RangeWithNumber from '../inputs/RangeWithNumber.svelte'; import ColorInput from '../inputs/ColorInput.svelte'; + import Section from '../inputs/Section.svelte'; let { tokens, overrides, onSet, onReset, onBulkChange, onSelectDomain }: { tokens: SlashedToken[]; @@ -520,16 +521,7 @@
-
- - {#if showBrandSources} +

OKLCH source values — all 200+ derived color steps are computed automatically. Tints (50–400) mix toward Base (the "Surface" color) and shades (600–950) mix toward Text (driven by Neutral) — so editing Base or Neutral below @@ -639,22 +631,12 @@ {/each} - {/if} -

+
-
- - {#if showLumlocker} +

Pins brand colors (primary, secondary, tertiary, action) to a fixed OKLCH lightness — useful for always-stable sections. Enable on canvas to preview. @@ -697,22 +679,12 @@ : "border-black/10 dark:border-white/10 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" }`} >{lumlockerPreview.value ? "✓ LumLocker active on canvas — click to disable" : "Preview LumLocker on live canvas"} - {/if} -

+
-
- - {#if showStatus} +

Dark mode is auto-derived from each light source by default. Switch to Manual dark to set a bespoke dark value. @@ -797,22 +769,12 @@ {/each} - {/if} -

+
-
- - {#if showTextContrast} +

Controls whether text on brand-coloured surfaces is light or dark.

@@ -858,22 +820,12 @@ onChange={(name, val) => val === null ? onReset(name) : onSet(name, val)} /> {/each} - {/if} -
+
-
- - {#if showShadeCurve} +
{@const _curvePrimLightSrc = overrides["--sf-color-primary-source-light"] ?? BRAND_SOURCES.find(s => s.name === "--sf-color-primary-source-light")?.default ?? "oklch(0.47 0.27 264)"} {@const _curvePrimDarkOv = overrides["--sf-color-primary-source-dark"]} {@const _curvePrimDarkSrc = _curvePrimDarkOv ?? (!autoDarkSet.has("primary") || _curvePrimDarkOv @@ -988,22 +940,12 @@ {/each} - {/if} -
+
-
- - {#if showGradients} +

Auto-derived from your brand colors. Use the angle/direction and stop controls, or edit the raw value for full control. @@ -1085,22 +1027,12 @@ {/each} {/each} - {/if} -

+
-
- - {#if showColorScheme} +

--sf-color-scheme — sets the CSS color-scheme property on the root, controlling browser UI (scrollbars, inputs) and default background.

@@ -1117,22 +1049,12 @@ >{label} {/each} - {/if} -
+
-
- - {#if showSemanticOverrides} +

Direct color overrides for tokens the framework auto-derives. Use for edge cases.

@@ -1152,8 +1074,7 @@ {/each} - {/if} -
+

diff --git a/configurator/src/components/panels/ComponentsPanel.svelte b/configurator/src/components/panels/ComponentsPanel.svelte index 76b807057..f81d97cc5 100644 --- a/configurator/src/components/panels/ComponentsPanel.svelte +++ b/configurator/src/components/panels/ComponentsPanel.svelte @@ -1,5 +1,6 @@