Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .claude/hooks/session-start.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/bash
set -euo pipefail

if [ "${CLAUDE_CODE_REMOTE:-}" != "true" ]; then
exit 0
fi

cd "${CLAUDE_PROJECT_DIR:-$(git rev-parse --show-toplevel)}"

# Install root dependencies (includes commitlint, stylelint, etc.)
npm install

# Wire up .githooks so the commit-msg hook runs commitlint pre-commit
npm run prepare
14 changes: 14 additions & 0 deletions .claude/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/session-start.sh"
}
]
}
]
}
}
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ playwright-report/
*.tgz
.DS_Store
.agents/
.claude/
.claude/*.lock
.claude/todos/
.claude/cache/

# Semantic review artifacts (sub-agent output, not source)
semantic-review/
Expand Down
1 change: 1 addition & 0 deletions configurator/src/components/panels/AllTokensTab.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
</button>
<button
onclick={() => { showInternal = !showInternal; }}
aria-expanded={showInternal}
class={`flex items-center gap-1 text-[9px] font-bold transition-colors cursor-pointer ${showInternal ? "text-amber-400" : "text-slate-600 hover:text-slate-400"}`}
>
<div class={`w-2.5 h-2.5 rounded border flex items-center justify-center transition-colors ${showInternal ? "bg-amber-600 border-amber-500" : "border-white/20"}`}>
Expand Down
398 changes: 235 additions & 163 deletions configurator/src/components/panels/BordersPanel.svelte

Large diffs are not rendered by default.

76 changes: 71 additions & 5 deletions configurator/src/components/panels/ColorsPanel.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,9 @@
(k) => k.name === "--sf-focus-ring-width"
);

let showBrandSources = $state(true);
let showTextContrast = $state(true);
let showShadeCurve = $state(true);
let showStatus = $state(false);
let showSemanticOverrides = $state(false);
let showGradients = $state(false);
Expand Down Expand Up @@ -323,7 +326,15 @@

<!-- BRAND SOURCES -->
<section class="space-y-3">
<div class="text-[10px] font-bold text-slate-500 uppercase tracking-widest">Brand color sources</div>
<button
onclick={() => { showBrandSources = !showBrandSources; }}
aria-expanded={showBrandSources}
class="w-full flex items-center justify-between cursor-pointer"
>
<div class="text-[10px] font-bold text-slate-500 uppercase tracking-widest">Brand color sources</div>
<span class="text-[10px] text-slate-500">{showBrandSources ? "▲" : "▼"}</span>
</button>
{#if showBrandSources}
<p class="text-[10px] text-slate-600 leading-relaxed">
OKLCH source values — all 200+ derived color steps are computed automatically.
</p>
Expand Down Expand Up @@ -409,6 +420,7 @@
</div>
{/each}
</div>
{/if}
</section>

<div class="h-px bg-white/6"></div>
Expand All @@ -417,6 +429,7 @@
<section class="space-y-3">
<button
onclick={() => { showLumlocker = !showLumlocker; }}
aria-expanded={showLumlocker}
class="w-full flex items-center justify-between cursor-pointer"
>
<div class="text-[10px] font-bold text-slate-500 uppercase tracking-widest">LumLocker</div>
Expand Down Expand Up @@ -474,6 +487,7 @@
<section class="space-y-3">
<button
onclick={() => { showStatus = !showStatus; }}
aria-expanded={showStatus}
class="w-full flex items-center justify-between cursor-pointer"
>
<div class="text-[10px] font-bold text-slate-500 uppercase tracking-widest">Status colors</div>
Expand Down Expand Up @@ -531,7 +545,15 @@

<!-- TEXT CONTRAST -->
<section class="space-y-4">
<div class="text-[10px] font-bold text-slate-500 uppercase tracking-widest">Text contrast</div>
<button
onclick={() => { showTextContrast = !showTextContrast; }}
aria-expanded={showTextContrast}
class="w-full flex items-center justify-between cursor-pointer"
>
<div class="text-[10px] font-bold text-slate-500 uppercase tracking-widest">Text contrast</div>
<span class="text-[10px] text-slate-500">{showTextContrast ? "▲" : "▼"}</span>
</button>
{#if showTextContrast}
<p class="text-[10px] text-slate-600 leading-relaxed">
Controls whether text on brand-coloured surfaces is light or dark.
</p>
Expand Down Expand Up @@ -577,13 +599,22 @@
onChange={(name, val) => val === null ? onReset(name) : onSet(name, val)}
/>
{/each}
{/if}
</section>

<div class="h-px bg-white/6"></div>

<!-- SHADE CURVE -->
<section class="space-y-4">
<div class="text-[10px] font-bold text-slate-500 uppercase tracking-widest">Shade / tint curve</div>
<button
onclick={() => { showShadeCurve = !showShadeCurve; }}
aria-expanded={showShadeCurve}
class="w-full flex items-center justify-between cursor-pointer"
>
<div class="text-[10px] font-bold text-slate-500 uppercase tracking-widest">Shade / tint curve</div>
<span class="text-[10px] text-slate-500">{showShadeCurve ? "▲" : "▼"}</span>
</button>
{#if showShadeCurve}
<p class="text-[10px] text-slate-600 leading-relaxed">
Controls how much color is mixed into each palette step. Step 500 is always the source color.
</p>
Expand Down Expand Up @@ -672,6 +703,39 @@
</div>
<p class="text-[8px] text-slate-600 mt-2">Bar height = mix amount · fill = the resolved primary palette swatch at each step</p>
</div>

<!-- Mini palettes: all brand colors × all steps, reactive to light/dark toggle -->
<div class="bg-white/4 rounded-xl border border-white/8 p-3 space-y-2">
<div class="flex items-center justify-between mb-1">
<span class="text-[9px] text-slate-600">Mini palettes — all brand colors</span>
<div class="flex bg-white/5 border border-white/8 rounded p-0.5 gap-0.5">
{#each ["light", "dark"] as side (side)}
<button
onclick={() => { curvePreviewSide = side as "light" | "dark"; }}
class={`px-1.5 py-0.5 rounded text-[8px] font-bold cursor-pointer transition-all ${
curvePreviewSide === side ? "bg-white/12 text-white" : "text-slate-500 hover:text-slate-300"
}`}
>{side === "light" ? "Light" : "Dark"}</button>
{/each}
</div>
</div>
{#each BRAND_COLOR_KEYS as colorKey (colorKey)}
<div class="flex items-center gap-1.5">
<span class="text-[7px] font-mono text-slate-600 w-12 shrink-0 truncate">{colorKey}</span>
<div class="flex gap-0.5 flex-1">
{#each SWATCH_STEPS as step (step)}
{@const swatch = paintTheme(`var(--sf-color-${colorKey}-${step})`, curvePreviewSide, `var(--sf-color-${colorKey}-${step})`)}
<div
class="flex-1 h-4 rounded-sm border border-white/10"
style={`background:${swatch}`}
title={`${colorKey}-${step} (${curvePreviewSide})`}
></div>
{/each}
</div>
</div>
{/each}
</div>
{/if}
</section>

<div class="h-px bg-white/6"></div>
Expand All @@ -680,6 +744,7 @@
<section class="space-y-3">
<button
onclick={() => { showGradients = !showGradients; }}
aria-expanded={showGradients}
class="w-full flex items-center justify-between cursor-pointer"
>
<div class="text-[10px] font-bold text-slate-500 uppercase tracking-widest">Gradients</div>
Expand Down Expand Up @@ -707,7 +772,7 @@
</div>

<!-- Structured controls -->
{#if g.kind === "dir"}
{#if g.kind === "dir" && g.group !== "fade"}
<div class="flex items-center gap-1">
<span class="text-[8px] text-slate-500 w-10 shrink-0">Dir</span>
{#each ["top", "right", "bottom", "left"] as d (d)}
Expand All @@ -719,7 +784,7 @@
>{d}</button>
{/each}
</div>
{:else}
{:else if g.kind !== "dir"}
<div class="flex items-center gap-2">
<span class="text-[8px] text-slate-500 w-10 shrink-0">Angle</span>
<input
Expand Down Expand Up @@ -776,6 +841,7 @@
<section class="space-y-3">
<button
onclick={() => { showSemanticOverrides = !showSemanticOverrides; }}
aria-expanded={showSemanticOverrides}
class="w-full flex items-center justify-between cursor-pointer"
>
<div class="text-[10px] font-bold text-slate-500 uppercase tracking-widest">Semantic overrides</div>
Expand Down
Loading
Loading