diff --git a/configurator/src/components/panels/MacrosPanel.svelte b/configurator/src/components/panels/MacrosPanel.svelte index bcb14431..18d3f641 100644 --- a/configurator/src/components/panels/MacrosPanel.svelte +++ b/configurator/src/components/panels/MacrosPanel.svelte @@ -33,6 +33,30 @@ { label: "↖ top-left", value: "to top left" }, ]; + // Enumerable presets for the .sf-surface-bg named-background macro. The first + // value in each list is the token default, so clicking it resets the override. + const SURFACE_BG_SIZE = ["cover", "contain", "auto", "100% 100%"]; + const SURFACE_BG_POSITION = ["center", "top", "bottom", "left", "right", "top left"]; + const SURFACE_BG_REPEAT = ["no-repeat", "repeat", "repeat-x", "repeat-y", "space", "round"]; + const SURFACE_BG_ATTACHMENT = ["scroll", "fixed", "local"]; + + // Free-form surface-bg tokens (color/image/overlay/animation) — plain text + // inputs, since their values are arbitrary CSS (urls, gradients, keyframes). + const SURFACE_BG_TEXT = [ + { label: "Color", token: "--sf-surface-bg-color", placeholder: "transparent" }, + { label: "Image", token: "--sf-surface-bg-image", placeholder: 'url("/hero.avif")' }, + { label: "Overlay", token: "--sf-surface-bg-overlay", placeholder: "var(--sf-scrim-gradient)" }, + { label: "Animation", token: "--sf-surface-bg-animation", placeholder: "sf-pan 40s linear infinite" }, + ]; + + // Enumerable surface-bg tokens rendered as preset button grids. + const SURFACE_BG_ENUM = [ + { label: "Size", token: "--sf-surface-bg-size", opts: SURFACE_BG_SIZE }, + { label: "Position", token: "--sf-surface-bg-position", opts: SURFACE_BG_POSITION }, + { label: "Repeat", token: "--sf-surface-bg-repeat", opts: SURFACE_BG_REPEAT }, + { label: "Attachment", token: "--sf-surface-bg-attachment", opts: SURFACE_BG_ATTACHMENT }, + ]; + // Prose spacing knobs. Defaults reference space tokens — the numbers below are // the approximate resolved rem values, used only as the slider's idle position. const PROSE_SPACE = [ @@ -52,6 +76,7 @@ let showScrim = $state(false); let showProse = $state(false); let showContentIntrinsic = $state(false); + let showSurfaceBg = $state(false); let lineClamp = $derived(num("--sf-line-clamp", 3)); let flowSpace = $derived(num("--sf-flow-space", 0.5, "rem")); @@ -61,6 +86,17 @@ let scrimDir = $derived(overrides["--sf-scrim-direction"] ?? "to top"); let mediaRadius = $derived(num("--sf-prose-media-radius", 6, "px")); + // Live preview composition for .sf-surface-bg — mirrors the macro's layering + // (overlay above image) so the swatch reflects what ships. + let surfaceBgImage = $derived(overrides["--sf-surface-bg-image"] ?? "none"); + let surfaceBgOverlay = $derived(overrides["--sf-surface-bg-overlay"] ?? "none"); + let surfaceBgColor = $derived(overrides["--sf-surface-bg-color"] ?? "transparent"); + let surfaceBgSize = $derived(overrides["--sf-surface-bg-size"] ?? "cover"); + let surfaceBgPosition = $derived(overrides["--sf-surface-bg-position"] ?? "center"); + let surfaceBgRepeat = $derived(overrides["--sf-surface-bg-repeat"] ?? "no-repeat"); + let surfaceBgAttachment = $derived(overrides["--sf-surface-bg-attachment"] ?? "scroll"); + let surfaceBgAnimation = $derived(overrides["--sf-surface-bg-animation"] ?? "none"); + function proseVal(t: typeof PROSE_SPACE[0]): number { const raw = overrides[t.token]; if (!raw) return t.def; @@ -367,6 +403,70 @@ {/if} +
+ + +
+ + {#if showSurfaceBg} +

+ --sf-surface-bg-* — input set composed by the .sf-surface-bg + macro into a single reusable background (color, image, overlay, sizing and animation). +

+ + {#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} +
+ {/each} + + {#each SURFACE_BG_ENUM as g (g.token)} +
+
{g.label}
+
+ {#each g.opts as opt (opt)} + + {/each} +
+
+ {/each} + +
+ .sf-surface-bg preview +
+ {/if} +
+

All tokens tab — edit every prose, scrim and surface token directly. diff --git a/configurator/src/data/domain-patterns.json b/configurator/src/data/domain-patterns.json index cd9452ee..39c57052 100644 --- a/configurator/src/data/domain-patterns.json +++ b/configurator/src/data/domain-patterns.json @@ -1,5 +1,5 @@ { - "macros": ["prose", "flow-space", "line-clamp", "aspect", "scroll-shadow", "scrim", "surface-color", "content-intrinsic", "corner-scoop", "overlap-"], + "macros": ["prose", "flow-space", "line-clamp", "aspect", "scroll-shadow", "scrim", "surface-color", "surface-bg", "content-intrinsic", "corner-scoop", "overlap-"], "colors": ["color", "contrast", "palette-mix", "lumlocker", "gradient"], "typography": ["font", "--sf-text", "leading", "tracking", "weight", "body-font", "heading-font", "body-em", "body-text", "heading-text", "display-l-", "display-m-",