Skip to content

Commit a21bb12

Browse files
committed
Simplify overlay-token applier: lookup table + isLightRgb helper
Collapse the 5 sequential setProperty calls into a [token, lightAlpha, darkAlpha] table so the App.svelte and index.html applier paths cannot silently drift on alpha tweaks. Extract isLightRgb() in color.ts so App.svelte stops duplicating the BT.601 luma formula. Name the bg-secondary RGB step as BG_SECONDARY_SHIFT.
1 parent 78cd186 commit a21bb12

3 files changed

Lines changed: 51 additions & 56 deletions

File tree

frontend/index.html

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@
2020
);
2121
}
2222
if (colors.background) {
23-
// Match overlay tokens to bg luminance so panels,
24-
// hovers, and borders stay visible on light themes.
23+
// Mirrors OVERLAY_TOKENS / BG_SECONDARY_SHIFT in
24+
// App.svelte. Inlined because this script runs
25+
// before the module bundle and cannot import.
2526
var bgHex = colors.background.replace('#', '');
2627
var br = parseInt(bgHex.slice(0, 2), 16);
2728
var bgg = parseInt(bgHex.slice(2, 4), 16);
@@ -33,6 +34,13 @@
3334
return Math.max(0, Math.min(255, n));
3435
};
3536
var ov = isLightBg ? '0,0,0' : '255,255,255';
37+
var overlayTokens = [
38+
['--color-bg-surface', 0.03, 0.04],
39+
['--color-bg-elevated', 0.06, 0.07],
40+
['--color-bg-hover', 0.04, 0.05],
41+
['--color-border', 0.1, 0.08],
42+
['--color-border-focus', 0.2, 0.18],
43+
];
3644
root.style.setProperty(
3745
'--color-bg-primary',
3846
colors.background
@@ -47,26 +55,17 @@
4755
clamp(bb + shift) +
4856
')'
4957
);
50-
root.style.setProperty(
51-
'--color-bg-surface',
52-
'rgba(' + ov + ',' + (isLightBg ? 0.03 : 0.04) + ')'
53-
);
54-
root.style.setProperty(
55-
'--color-bg-elevated',
56-
'rgba(' + ov + ',' + (isLightBg ? 0.06 : 0.07) + ')'
57-
);
58-
root.style.setProperty(
59-
'--color-bg-hover',
60-
'rgba(' + ov + ',' + (isLightBg ? 0.04 : 0.05) + ')'
61-
);
62-
root.style.setProperty(
63-
'--color-border',
64-
'rgba(' + ov + ',' + (isLightBg ? 0.1 : 0.08) + ')'
65-
);
66-
root.style.setProperty(
67-
'--color-border-focus',
68-
'rgba(' + ov + ',' + (isLightBg ? 0.2 : 0.18) + ')'
69-
);
58+
for (var i = 0; i < overlayTokens.length; i++) {
59+
var t = overlayTokens[i];
60+
root.style.setProperty(
61+
t[0],
62+
'rgba(' +
63+
ov +
64+
',' +
65+
(isLightBg ? t[1] : t[2]) +
66+
')'
67+
);
68+
}
7069
document.body.style.background = colors.background;
7170
}
7271
if (colors.foreground) {

frontend/src/App.svelte

Lines changed: 25 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@
7878
import KeymapDialog from '$lib/components/shared/KeymapDialog.svelte';
7979
import CommandPalette from '$lib/components/shared/CommandPalette.svelte';
8080
import {initKeyboardShortcuts, registerShortcut} from '$lib/utils/keyboard';
81-
import {hexToRgb} from '$lib/utils/color';
81+
import {hexToRgb, isLightRgb} from '$lib/utils/color';
8282
import {buildCommands} from '$lib/commands/commands.svelte';
8383
import type {main} from '../wailsjs/go/models';
8484
@@ -88,6 +88,19 @@
8888
let sliderWidget = $state(false);
8989
let themesSlider = $state(false);
9090
91+
// RGB step between bg-primary and bg-secondary so panels stay
92+
// visually layered on any theme bg.
93+
const BG_SECONDARY_SHIFT = 10;
94+
// CSS tokens layered over bg-primary, paired with their alpha values
95+
// for light and dark backgrounds. Order: [token, lightAlpha, darkAlpha].
96+
const OVERLAY_TOKENS: ReadonlyArray<[string, number, number]> = [
97+
['--color-bg-surface', 0.03, 0.04],
98+
['--color-bg-elevated', 0.06, 0.07],
99+
['--color-bg-hover', 0.04, 0.05],
100+
['--color-border', 0.1, 0.08],
101+
['--color-border-focus', 0.2, 0.18],
102+
];
103+
91104
// Mirror editor state into Go (debounced) so `aether status` and other IPC
92105
// readers reflect live edits without waiting for an Apply. Long enough
93106
// to cover slider drags; first sync on mount posts the initial snapshot.
@@ -269,46 +282,27 @@
269282
}
270283
if (colors.background) {
271284
const bg = hexToRgb(colors.background);
272-
// Luma threshold matches isLightColor() — a light
273-
// omarchy theme needs dark scrim/border overlays, a
274-
// dark theme needs the white-on-dark defaults.
275-
const isLightBg =
276-
(bg.r * 299 + bg.g * 587 + bg.b * 114) / 1000 > 128;
277-
const shift = isLightBg ? -10 : 10;
285+
const isLightBg = isLightRgb(bg.r, bg.g, bg.b);
286+
const shift = isLightBg
287+
? -BG_SECONDARY_SHIFT
288+
: BG_SECONDARY_SHIFT;
278289
const clamp = (n: number) =>
279290
Math.max(0, Math.min(255, n));
280-
const bg2r = clamp(bg.r + shift);
281-
const bg2g = clamp(bg.g + shift);
282-
const bg2b = clamp(bg.b + shift);
283291
const overlay = isLightBg ? '0, 0, 0' : '255, 255, 255';
284292
root.style.setProperty(
285293
'--color-bg-primary',
286294
colors.background
287295
);
288296
root.style.setProperty(
289297
'--color-bg-secondary',
290-
`rgb(${bg2r}, ${bg2g}, ${bg2b})`
291-
);
292-
root.style.setProperty(
293-
'--color-bg-surface',
294-
`rgba(${overlay}, ${isLightBg ? 0.03 : 0.04})`
295-
);
296-
root.style.setProperty(
297-
'--color-bg-elevated',
298-
`rgba(${overlay}, ${isLightBg ? 0.06 : 0.07})`
299-
);
300-
root.style.setProperty(
301-
'--color-bg-hover',
302-
`rgba(${overlay}, ${isLightBg ? 0.04 : 0.05})`
303-
);
304-
root.style.setProperty(
305-
'--color-border',
306-
`rgba(${overlay}, ${isLightBg ? 0.1 : 0.08})`
307-
);
308-
root.style.setProperty(
309-
'--color-border-focus',
310-
`rgba(${overlay}, ${isLightBg ? 0.2 : 0.18})`
298+
`rgb(${clamp(bg.r + shift)}, ${clamp(bg.g + shift)}, ${clamp(bg.b + shift)})`
311299
);
300+
for (const [token, lightA, darkA] of OVERLAY_TOKENS) {
301+
root.style.setProperty(
302+
token,
303+
`rgba(${overlay}, ${isLightBg ? lightA : darkA})`
304+
);
305+
}
312306
document.body.style.background = colors.background;
313307
WindowSetBackgroundColour(bg.r, bg.g, bg.b, 255);
314308
}

frontend/src/lib/utils/color.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ import {showToast} from '$lib/stores/ui.svelte';
66
*/
77
export function isLightColor(hex: string): boolean {
88
if (!hex || hex.length < 7) return false;
9-
const r = parseInt(hex.slice(1, 3), 16);
10-
const g = parseInt(hex.slice(3, 5), 16);
11-
const b = parseInt(hex.slice(5, 7), 16);
9+
const {r, g, b} = hexToRgb(hex);
10+
return isLightRgb(r, g, b);
11+
}
12+
13+
export function isLightRgb(r: number, g: number, b: number): boolean {
1214
return (r * 299 + g * 587 + b * 114) / 1000 > 128;
1315
}
1416

0 commit comments

Comments
 (0)