Skip to content

Commit 07bb1bd

Browse files
committed
Refine light theme differentiation
1 parent eea0431 commit 07bb1bd

4 files changed

Lines changed: 207 additions & 80 deletions

File tree

packages/web/src/styles/tokens-touch.test.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ function getRuleBlock(selector: string): string {
2020
return block;
2121
}
2222

23+
function getCustomProperty(block: string, name: string): string | null {
24+
const match = new RegExp(`${name}:\\s*([^;]+);`).exec(block);
25+
return match?.[1]?.trim() ?? null;
26+
}
27+
2328
describe("tokens.css touch tokens", () => {
2429
it("defines named theme blocks for all built-in themes", () => {
2530
expect(stylesheet).toContain(':root,\n[data-theme="mint-dark"]');
@@ -55,4 +60,42 @@ describe("tokens.css touch tokens", () => {
5560
expect(body).toContain("--touch-spacing-min: 12px");
5661
expect(body).toContain("--touch-hit-slop: 8px");
5762
});
63+
64+
it("keeps the light theme families visually separated through structure tokens", () => {
65+
const mintLight = getRuleBlock('[data-theme="mint-light"]');
66+
const graphiteLight = getRuleBlock('[data-theme="graphite-light"]');
67+
const nordLight = getRuleBlock('[data-theme="nord-light"]');
68+
69+
expect(getCustomProperty(mintLight, "--bg-page")).toBe("#f3fbf7");
70+
expect(getCustomProperty(mintLight, "--bg-sidebar")).toBe("#edf7f2");
71+
expect(getCustomProperty(mintLight, "--border-focus")).toBe("#158f77");
72+
73+
expect(getCustomProperty(graphiteLight, "--bg-page")).toBe("#e7edf3");
74+
expect(getCustomProperty(graphiteLight, "--bg-sidebar")).toBe("#dfe6ee");
75+
expect(getCustomProperty(graphiteLight, "--border-focus")).toBe("#315fdd");
76+
77+
expect(getCustomProperty(nordLight, "--bg-page")).toBe("#e3ebf4");
78+
expect(getCustomProperty(nordLight, "--bg-sidebar")).toBe("#dbe4ef");
79+
expect(getCustomProperty(nordLight, "--border-focus")).toBe("#5b7fa8");
80+
});
81+
82+
it("separates the light theme interaction palette across families", () => {
83+
const mintLight = getRuleBlock('[data-theme="mint-light"]');
84+
const graphiteLight = getRuleBlock('[data-theme="graphite-light"]');
85+
const nordLight = getRuleBlock('[data-theme="nord-light"]');
86+
87+
expect(getCustomProperty(mintLight, "--text-secondary")).toBe("#557067");
88+
expect(getCustomProperty(mintLight, "--accent-blue")).toBe("#148a7a");
89+
expect(getCustomProperty(mintLight, "--shadow-glow")).toBe("0 0 12px rgba(21, 143, 119, 0.18)");
90+
91+
expect(getCustomProperty(graphiteLight, "--text-secondary")).toBe("#4d5b6a");
92+
expect(getCustomProperty(graphiteLight, "--accent-blue")).toBe("#315fdd");
93+
expect(getCustomProperty(graphiteLight, "--shadow-glow")).toBe(
94+
"0 0 12px rgba(49, 95, 221, 0.16)"
95+
);
96+
97+
expect(getCustomProperty(nordLight, "--text-secondary")).toBe("#4d5a6f");
98+
expect(getCustomProperty(nordLight, "--accent-blue")).toBe("#5b7fa8");
99+
expect(getCustomProperty(nordLight, "--shadow-glow")).toBe("0 0 12px rgba(91, 127, 168, 0.18)");
100+
});
58101
});

packages/web/src/styles/tokens.css

Lines changed: 35 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -182,30 +182,30 @@
182182

183183
[data-theme="mint-light"] {
184184
/* ========== Backgrounds ========== */
185-
--bg-page: #f8fafb;
186-
--bg-surface: #ffffff;
187-
--bg-sidebar: #f4f6f8;
185+
--bg-page: #f3fbf7;
186+
--bg-surface: #fcfffd;
187+
--bg-sidebar: #edf7f2;
188188
--bg-terminal: #fafbfc;
189-
--bg-hover: #e8ecf0;
190-
--bg-active: #dde4ea;
189+
--bg-hover: #ddefe5;
190+
--bg-active: #d1e8dc;
191191
--bg-disabled: #f0f3f6;
192192
--bg-input: #ffffff;
193193

194194
/* ========== Borders ========== */
195-
--border: #d0d7de;
196-
--border-light: #e1e4e8;
197-
--border-focus: #0969da;
195+
--border: #c7d8cf;
196+
--border-light: #d8e7df;
197+
--border-focus: #158f77;
198198
--border-error: #cf222e;
199199

200200
/* ========== Text ========== */
201201
--text-primary: #1f2328;
202-
--text-secondary: #57606a;
202+
--text-secondary: #557067;
203203
--text-tertiary: #8b949e;
204204
--text-disabled: #6e7681;
205205
--text-inverse: #ffffff;
206206

207207
/* ========== Accents ========== */
208-
--accent-blue: #0969da;
208+
--accent-blue: #148a7a;
209209
--accent-green: #1a7f37;
210210
--accent-amber: #9a6700;
211211
--accent-pink: #cf222e;
@@ -215,14 +215,14 @@
215215
--color-success: #1a7f37;
216216
--color-warning: #9a6700;
217217
--color-error: #cf222e;
218-
--color-info: #0969da;
218+
--color-info: #148a7a;
219219

220220
/* ========== Shadows ========== */
221221
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.08);
222222
--shadow-md: 0 4px 12px rgba(0, 0, 0, 0.1);
223223
--shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.12);
224224
--shadow-xl: 0 16px 48px rgba(0, 0, 0, 0.15);
225-
--shadow-glow: 0 0 12px rgba(9, 105, 218, 0.2);
225+
--shadow-glow: 0 0 12px rgba(21, 143, 119, 0.18);
226226

227227
/* Scrollbar */
228228
--scrollbar-thumb: #d0d7de;
@@ -278,30 +278,30 @@
278278

279279
[data-theme="graphite-light"] {
280280
/* ========== Backgrounds ========== */
281-
--bg-page: #edf1f5;
281+
--bg-page: #e7edf3;
282282
--bg-surface: #ffffff;
283-
--bg-sidebar: #e7ebf0;
283+
--bg-sidebar: #dfe6ee;
284284
--bg-terminal: #f3f4f6;
285-
--bg-hover: #dde3ea;
286-
--bg-active: #d2d9e2;
285+
--bg-hover: #d4dce5;
286+
--bg-active: #c8d1dc;
287287
--bg-disabled: #eef2f6;
288288
--bg-input: #ffffff;
289289

290290
/* ========== Borders ========== */
291-
--border: #c7d0da;
292-
--border-light: #d8dee6;
293-
--border-focus: #2563eb;
291+
--border: #b8c3cf;
292+
--border-light: #ccd5de;
293+
--border-focus: #315fdd;
294294
--border-error: #d14343;
295295

296296
/* ========== Text ========== */
297297
--text-primary: #1f2933;
298-
--text-secondary: #52606d;
298+
--text-secondary: #4d5b6a;
299299
--text-tertiary: #7b8794;
300300
--text-disabled: #9aa5b1;
301301
--text-inverse: #ffffff;
302302

303303
/* ========== Accents ========== */
304-
--accent-blue: #1d4ed8;
304+
--accent-blue: #315fdd;
305305
--accent-green: #15803d;
306306
--accent-amber: #a16207;
307307
--accent-pink: #d14343;
@@ -311,14 +311,14 @@
311311
--color-success: #15803d;
312312
--color-warning: #a16207;
313313
--color-error: #d14343;
314-
--color-info: #1d4ed8;
314+
--color-info: #315fdd;
315315

316316
/* ========== Shadows ========== */
317317
--shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.08);
318318
--shadow-md: 0 4px 12px rgba(15, 23, 42, 0.1);
319319
--shadow-lg: 0 8px 32px rgba(15, 23, 42, 0.12);
320320
--shadow-xl: 0 16px 48px rgba(15, 23, 42, 0.16);
321-
--shadow-glow: 0 0 12px rgba(29, 78, 216, 0.18);
321+
--shadow-glow: 0 0 12px rgba(49, 95, 221, 0.16);
322322

323323
/* Scrollbar */
324324
--scrollbar-thumb: #c7d0da;
@@ -374,30 +374,30 @@
374374

375375
[data-theme="nord-light"] {
376376
/* ========== Backgrounds ========== */
377-
--bg-page: #e8ecf2;
378-
--bg-surface: #eceff4;
379-
--bg-sidebar: #e1e7ef;
377+
--bg-page: #e3ebf4;
378+
--bg-surface: #f1f5fa;
379+
--bg-sidebar: #dbe4ef;
380380
--bg-terminal: #eceff4;
381-
--bg-hover: #dde3eb;
382-
--bg-active: #d8dee9;
381+
--bg-hover: #d2ddea;
382+
--bg-active: #c8d4e2;
383383
--bg-disabled: #edf1f6;
384384
--bg-input: #f7f9fc;
385385

386386
/* ========== Borders ========== */
387-
--border: #c6ceda;
388-
--border-light: #d8dee9;
389-
--border-focus: #5e81ac;
387+
--border: #b8c6d7;
388+
--border-light: #cad5e2;
389+
--border-focus: #5b7fa8;
390390
--border-error: #bf616a;
391391

392392
/* ========== Text ========== */
393393
--text-primary: #2e3440;
394-
--text-secondary: #4c566a;
394+
--text-secondary: #4d5a6f;
395395
--text-tertiary: #7b88a1;
396396
--text-disabled: #93a0b7;
397397
--text-inverse: #ffffff;
398398

399399
/* ========== Accents ========== */
400-
--accent-blue: #5e81ac;
400+
--accent-blue: #5b7fa8;
401401
--accent-green: #4c7a5b;
402402
--accent-amber: #a77f2f;
403403
--accent-pink: #bf616a;
@@ -407,14 +407,14 @@
407407
--color-success: #4c7a5b;
408408
--color-warning: #a77f2f;
409409
--color-error: #bf616a;
410-
--color-info: #5e81ac;
410+
--color-info: #5b7fa8;
411411

412412
/* ========== Shadows ========== */
413413
--shadow-sm: 0 1px 2px rgba(46, 52, 64, 0.08);
414414
--shadow-md: 0 4px 12px rgba(46, 52, 64, 0.1);
415415
--shadow-lg: 0 8px 32px rgba(46, 52, 64, 0.12);
416416
--shadow-xl: 0 16px 48px rgba(46, 52, 64, 0.15);
417-
--shadow-glow: 0 0 12px rgba(94, 129, 172, 0.2);
417+
--shadow-glow: 0 0 12px rgba(91, 127, 168, 0.18);
418418

419419
/* Scrollbar */
420420
--scrollbar-thumb: #c6ceda;

packages/web/src/theme/registry.test.ts

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,4 +92,88 @@ describe("theme registry", () => {
9292
);
9393
}
9494
});
95+
96+
it("keeps light terminal palettes separated by theme family", () => {
97+
const mintLight = THEMES.find((theme) => theme.id === "mint-light");
98+
const graphiteLight = THEMES.find((theme) => theme.id === "graphite-light");
99+
const nordLight = THEMES.find((theme) => theme.id === "nord-light");
100+
101+
expect(mintLight?.terminalTheme).toEqual(
102+
expect.objectContaining({
103+
background: "#fcfffd",
104+
cursor: "#148a7a",
105+
blue: "#148a7a",
106+
cyan: "#0f766e",
107+
selectionBackground: "#ddefe5",
108+
})
109+
);
110+
111+
expect(graphiteLight?.terminalTheme).toEqual(
112+
expect.objectContaining({
113+
background: "#f5f7fa",
114+
cursor: "#315fdd",
115+
blue: "#315fdd",
116+
cyan: "#1f6f8b",
117+
selectionBackground: "#d4dce5",
118+
})
119+
);
120+
121+
expect(nordLight?.terminalTheme).toEqual(
122+
expect.objectContaining({
123+
background: "#f1f5fa",
124+
cursor: "#5b7fa8",
125+
blue: "#5b7fa8",
126+
cyan: "#4c7f99",
127+
selectionBackground: "#d2ddea",
128+
})
129+
);
130+
});
131+
132+
it("keeps light monaco palettes separated by theme family", () => {
133+
const mintLight = THEMES.find((theme) => theme.id === "mint-light");
134+
const graphiteLight = THEMES.find((theme) => theme.id === "graphite-light");
135+
const nordLight = THEMES.find((theme) => theme.id === "nord-light");
136+
137+
expect(mintLight?.monaco.colors).toEqual(
138+
expect.objectContaining({
139+
"editor.background": "#fcfffd",
140+
"editorCursor.foreground": "#148a7a",
141+
"editor.selectionBackground": "#ddefe5",
142+
})
143+
);
144+
expect(mintLight?.monaco.rules).toEqual(
145+
expect.arrayContaining([
146+
expect.objectContaining({ token: "string", foreground: "18794e" }),
147+
expect.objectContaining({ token: "keyword", foreground: "148a7a" }),
148+
])
149+
);
150+
151+
expect(graphiteLight?.monaco.colors).toEqual(
152+
expect.objectContaining({
153+
"editor.background": "#f5f7fa",
154+
"editorCursor.foreground": "#315fdd",
155+
"editor.selectionBackground": "#d4dce5",
156+
})
157+
);
158+
expect(graphiteLight?.monaco.rules).toEqual(
159+
expect.arrayContaining([
160+
expect.objectContaining({ token: "string", foreground: "2f6f44" }),
161+
expect.objectContaining({ token: "keyword", foreground: "315fdd" }),
162+
])
163+
);
164+
165+
expect(nordLight?.monaco.colors).toEqual(
166+
expect.objectContaining({
167+
"editor.background": "#f1f5fa",
168+
"editorCursor.foreground": "#5b7fa8",
169+
"editor.selectionBackground": "#d2ddea",
170+
})
171+
);
172+
expect(nordLight?.monaco.rules).toEqual(
173+
expect.arrayContaining([
174+
expect.objectContaining({ token: "string", foreground: "5d7a66" }),
175+
expect.objectContaining({ token: "keyword", foreground: "5b7fa8" }),
176+
])
177+
);
178+
});
95179
});

0 commit comments

Comments
 (0)