Skip to content

Commit 21824c3

Browse files
MrScriptyclaude
andcommitted
refactor(ui): extract CSS theme variables and centralize styling
Replace hardcoded hex colors across all Svelte components and dockview theme with CSS custom properties defined in theme.css. Canvas-drawn widgets (color wheels, curves) use getCanvasTheme() from theme.ts. This centralizes the dark theme palette so future theme changes or light mode support only require editing one file. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 97f9732 commit 21824c3

16 files changed

Lines changed: 263 additions & 97 deletions

crates/crispen-demo/ui/index.html

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,7 @@
44
<meta charset="UTF-8" />
55
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
66
<title>Crispen</title>
7-
<style>
8-
html,
9-
body {
10-
margin: 0;
11-
padding: 0;
12-
background: transparent;
13-
overflow: hidden;
14-
width: 100%;
15-
height: 100%;
16-
}
17-
#app {
18-
position: fixed;
19-
top: 0;
20-
left: 0;
21-
width: 100%;
22-
height: 100%;
23-
}
24-
</style>
7+
<!-- All styles live in theme.css, imported by main.ts -->
258
</head>
269
<body>
2710
<div id="app"></div>

crates/crispen-demo/ui/src/lib/components/ColorSpaceSelector.svelte

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@
9191
margin: 0 0 8px;
9292
font-size: 13px;
9393
font-weight: 500;
94-
color: #aaa;
94+
color: var(--color-text-heading);
9595
}
9696
9797
.selector-row {
@@ -107,16 +107,16 @@
107107
.selector-row span {
108108
width: 60px;
109109
font-size: 11px;
110-
color: #888;
110+
color: var(--color-text-secondary);
111111
}
112112
113113
.selector-row select {
114114
flex: 1;
115115
padding: 3px 6px;
116-
background: #2a2a2a;
117-
border: 1px solid #444;
116+
background: var(--color-bg-surface-alt);
117+
border: 1px solid var(--color-border-subtle);
118118
border-radius: 3px;
119-
color: #e0e0e0;
119+
color: var(--color-text-primary);
120120
font-size: 11px;
121121
}
122122
</style>

crates/crispen-demo/ui/src/lib/components/ColorWheels.svelte

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<script lang="ts">
22
import type { GradingParams } from '$lib/types';
33
import { bridge } from '$lib/bridge';
4+
import { getCanvasTheme } from '$lib/theme';
45
import { onMount } from 'svelte';
56
67
let { params }: { params: GradingParams } = $props();
@@ -147,6 +148,7 @@
147148
const ctx = canvas.getContext('2d');
148149
if (!ctx) return;
149150
151+
const theme = getCanvasTheme();
150152
const s = WHEEL_SIZE;
151153
const cx = s / 2;
152154
const cy = s / 2;
@@ -156,7 +158,7 @@
156158
ctx.clearRect(0, 0, s, s);
157159
158160
// Dark background circle.
159-
ctx.fillStyle = '#1a1a1a';
161+
ctx.fillStyle = theme.bgCanvas;
160162
ctx.beginPath();
161163
ctx.arc(cx, cy, outerR, 0, Math.PI * 2);
162164
ctx.fill();
@@ -174,13 +176,13 @@
174176
}
175177
176178
// Inner disc.
177-
ctx.fillStyle = '#222';
179+
ctx.fillStyle = theme.bgInnerDisc;
178180
ctx.beginPath();
179181
ctx.arc(cx, cy, innerR - 1, 0, Math.PI * 2);
180182
ctx.fill();
181183
182184
// Crosshair.
183-
ctx.strokeStyle = 'rgba(255, 255, 255, 0.15)';
185+
ctx.strokeStyle = theme.crosshair;
184186
ctx.lineWidth = 1;
185187
ctx.beginPath();
186188
ctx.moveTo(cx, cy - innerR + 4);
@@ -203,16 +205,16 @@
203205
const indicatorY = cy - py * scale; // flip Y
204206
205207
// Indicator dot.
206-
ctx.fillStyle = '#f28c18';
207-
ctx.strokeStyle = '#fff';
208+
ctx.fillStyle = theme.accent;
209+
ctx.strokeStyle = theme.textTitle;
208210
ctx.lineWidth = 1.5;
209211
ctx.beginPath();
210212
ctx.arc(indicatorX, indicatorY, 5, 0, Math.PI * 2);
211213
ctx.fill();
212214
ctx.stroke();
213215
214216
// Center dot.
215-
ctx.fillStyle = 'rgba(255, 255, 255, 0.3)';
217+
ctx.fillStyle = theme.center;
216218
ctx.beginPath();
217219
ctx.arc(cx, cy, 2, 0, Math.PI * 2);
218220
ctx.fill();
@@ -278,7 +280,7 @@
278280
margin: 0 0 8px;
279281
font-size: 13px;
280282
font-weight: 500;
281-
color: #aaa;
283+
color: var(--color-text-heading);
282284
}
283285
284286
.wheels-grid {
@@ -288,15 +290,15 @@
288290
}
289291
290292
.wheel-group {
291-
background: #252525;
293+
background: var(--color-bg-surface);
292294
border-radius: 6px;
293295
padding: 8px;
294296
}
295297
296298
.wheel-label {
297299
display: block;
298300
font-size: 11px;
299-
color: #888;
301+
color: var(--color-text-secondary);
300302
text-transform: capitalize;
301303
margin-bottom: 4px;
302304
text-align: center;
@@ -330,17 +332,17 @@
330332
331333
.channel-label {
332334
font-size: 10px;
333-
color: #666;
335+
color: var(--color-text-tertiary);
334336
margin-bottom: 2px;
335337
}
336338
337339
.channel input {
338340
width: 100%;
339341
padding: 2px 4px;
340-
background: #1a1a1a;
341-
border: 1px solid #444;
342+
background: var(--color-bg-canvas);
343+
border: 1px solid var(--color-border-subtle);
342344
border-radius: 3px;
343-
color: #e0e0e0;
345+
color: var(--color-text-primary);
344346
font-size: 11px;
345347
text-align: center;
346348
}

crates/crispen-demo/ui/src/lib/components/CurveEditor.svelte

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<script lang="ts">
22
import type { GradingParams } from '$lib/types';
33
import { bridge } from '$lib/bridge';
4+
import { getCanvasTheme } from '$lib/theme';
45
import { onMount } from 'svelte';
56
67
let { params }: { params: GradingParams } = $props();
@@ -187,15 +188,16 @@
187188
const ctx = canvas.getContext('2d');
188189
if (!ctx) return;
189190
191+
const theme = getCanvasTheme();
190192
const cfg = curveConfig();
191193
const pts = curvePoints();
192194
193195
ctx.clearRect(0, 0, SIZE, SIZE);
194-
ctx.fillStyle = '#1a1a1a';
196+
ctx.fillStyle = theme.bgCanvas;
195197
ctx.fillRect(0, 0, SIZE, SIZE);
196198
197199
// Grid.
198-
ctx.strokeStyle = 'rgba(255, 255, 255, 0.08)';
200+
ctx.strokeStyle = theme.grid;
199201
ctx.lineWidth = 1;
200202
for (let i = 0; i <= 4; i++) {
201203
const frac = i / 4;
@@ -212,13 +214,13 @@
212214
}
213215
214216
// Plot border.
215-
ctx.strokeStyle = 'rgba(255, 255, 255, 0.15)';
217+
ctx.strokeStyle = theme.crosshair;
216218
ctx.strokeRect(PAD, PAD, PLOT_SIZE, PLOT_SIZE);
217219
218220
// Identity line (horizontal at yIdentity).
219221
const [idLeft, idY] = dataToCanvas(0, cfg.yIdentity);
220222
const [idRight] = dataToCanvas(1, cfg.yIdentity);
221-
ctx.strokeStyle = 'rgba(255, 255, 255, 0.2)';
223+
ctx.strokeStyle = theme.identity;
222224
ctx.setLineDash([4, 4]);
223225
ctx.beginPath();
224226
ctx.moveTo(idLeft, idY);
@@ -228,7 +230,7 @@
228230
229231
// Interpolated curve.
230232
if (pts.length > 0) {
231-
ctx.strokeStyle = '#f28c18';
233+
ctx.strokeStyle = theme.accent;
232234
ctx.lineWidth = 2;
233235
ctx.beginPath();
234236
const steps = PLOT_SIZE;
@@ -246,8 +248,8 @@
246248
// Control points.
247249
for (let i = 0; i < pts.length; i++) {
248250
const [cx, cy] = dataToCanvas(pts[i][0], pts[i][1]);
249-
ctx.fillStyle = dragIndex === i ? '#fff' : '#f28c18';
250-
ctx.strokeStyle = '#fff';
251+
ctx.fillStyle = dragIndex === i ? theme.textTitle : theme.accent;
252+
ctx.strokeStyle = theme.textTitle;
251253
ctx.lineWidth = 1.5;
252254
ctx.beginPath();
253255
ctx.arc(cx, cy, 5, 0, Math.PI * 2);
@@ -256,7 +258,7 @@
256258
}
257259
258260
// Axis labels.
259-
ctx.fillStyle = '#555';
261+
ctx.fillStyle = theme.textDim;
260262
ctx.font = '9px sans-serif';
261263
ctx.textAlign = 'center';
262264
ctx.fillText(cfg.xLabel, PAD + PLOT_SIZE / 2, SIZE - 4);
@@ -267,7 +269,7 @@
267269
ctx.restore();
268270
269271
// Scale labels.
270-
ctx.fillStyle = '#444';
272+
ctx.fillStyle = theme.textHint;
271273
ctx.font = '8px sans-serif';
272274
ctx.textAlign = 'right';
273275
ctx.fillText(cfg.yMax.toFixed(1), PAD - 4, PAD + 4);
@@ -324,7 +326,7 @@
324326
margin: 0 0 8px;
325327
font-size: 13px;
326328
font-weight: 500;
327-
color: #aaa;
329+
color: var(--color-text-heading);
328330
}
329331
330332
.curve-tabs {
@@ -335,18 +337,18 @@
335337
336338
.curve-tab {
337339
padding: 4px 8px;
338-
background: #2a2a2a;
339-
border: 1px solid #444;
340+
background: var(--color-bg-surface-alt);
341+
border: 1px solid var(--color-border-subtle);
340342
border-radius: 3px;
341-
color: #888;
343+
color: var(--color-text-secondary);
342344
cursor: pointer;
343345
font-size: 10px;
344346
}
345347
346348
.curve-tab.active {
347-
background: #3a3a3a;
348-
color: #e0e0e0;
349-
border-color: #666;
349+
background: var(--color-bg-interactive);
350+
color: var(--color-text-primary);
351+
border-color: var(--color-border-active);
350352
}
351353
352354
.curve-canvas-wrap {
@@ -366,7 +368,7 @@
366368
367369
.curve-hint {
368370
font-size: 9px;
369-
color: #444;
371+
color: var(--color-text-hint);
370372
margin: 4px 0 0;
371373
}
372374
</style>

crates/crispen-demo/ui/src/lib/components/PrimaryBars.svelte

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,12 @@
1010
{ key: 'gain' as const, label: 'Gain', min: 0, max: 4, step: 0.01 },
1111
{ key: 'offset' as const, label: 'Offset', min: -1, max: 1, step: 0.01 },
1212
];
13-
const channelColors = ['#ff4444', '#44ff44', '#4488ff', '#cccccc'];
13+
const channelVars = [
14+
'var(--color-channel-r)',
15+
'var(--color-channel-g)',
16+
'var(--color-channel-b)',
17+
'var(--color-channel-master)',
18+
];
1419
1520
function updateBar(key: 'lift' | 'gamma' | 'gain' | 'offset', channel: number, value: number) {
1621
const updated = $state.snapshot(params) as GradingParams;
@@ -32,7 +37,7 @@
3237
max={bar.max}
3338
step={bar.step}
3439
value={params[bar.key][ch]}
35-
style="accent-color: {channelColors[ch]}"
40+
style="accent-color: {channelVars[ch]}"
3641
oninput={(e) => updateBar(bar.key, ch, parseFloat((e.target as HTMLInputElement).value))}
3742
/>
3843
{/each}
@@ -46,7 +51,7 @@
4651
margin: 16px 0 8px;
4752
font-size: 13px;
4853
font-weight: 500;
49-
color: #aaa;
54+
color: var(--color-text-heading);
5055
}
5156
5257
.bar-group {
@@ -56,7 +61,7 @@
5661
.bar-label {
5762
display: block;
5863
font-size: 11px;
59-
color: #888;
64+
color: var(--color-text-secondary);
6065
margin-bottom: 4px;
6166
}
6267

crates/crispen-demo/ui/src/lib/components/Sliders.svelte

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
margin: 16px 0 8px;
5151
font-size: 13px;
5252
font-weight: 500;
53-
color: #aaa;
53+
color: var(--color-text-heading);
5454
}
5555
5656
.slider-row {
@@ -64,7 +64,7 @@
6464
.slider-label {
6565
width: 110px;
6666
font-size: 11px;
67-
color: #888;
67+
color: var(--color-text-secondary);
6868
flex-shrink: 0;
6969
}
7070
@@ -78,7 +78,7 @@
7878
width: 50px;
7979
text-align: right;
8080
font-size: 11px;
81-
color: #ccc;
81+
color: var(--color-text-value);
8282
font-variant-numeric: tabular-nums;
8383
}
8484
</style>

0 commit comments

Comments
 (0)