8ea40260ad
- The lane terminal (xterm) takes its palette from the selected DARK theme — it stays dark in light mode, as a terminal should — and repaints live when the theme changes (`client/src/lib/terminalTheme.ts`). - Charts on the Dashboard and Workflows pages draw their grid, axes, labels and tooltips from theme tokens instead of hardcoded near-black/white, and the activity heatmap ramps from the page surface to the accent, so it reads on every theme instead of going near-black on light ones. - Status/brand text that only worked on dark backgrounds (`text-*-300/400`) gets a darker light-mode shade (`text-*-700 dark:text-*-300`) across sessions, conversations, workflows, config and settings. Categorical chart colours are kept.
72 lines
2.7 KiB
TypeScript
72 lines
2.7 KiB
TypeScript
/**
|
|
* @file terminalTheme.test.ts
|
|
* @description Tests for the xterm theme builder: CSS-variable RGB triplets
|
|
* become hex, status/accent map to the ANSI hues, bright twins are lighter,
|
|
* and the probe resolves a named dark theme's variables.
|
|
* @author Nguyễn Ngọc Trí Vĩ <vinnt@smartgift.vn>
|
|
*/
|
|
import { describe, it, expect } from "vitest";
|
|
import { buildTerminalTheme, terminalThemeFor } from "../terminalTheme";
|
|
|
|
const vars: Record<string, string> = {
|
|
"--surface-0": " 17 17 19",
|
|
"--surface-3": "39 42 45",
|
|
"--fg-primary": "237 238 240",
|
|
"--fg-secondary": "176 180 186",
|
|
"--fg-muted": "105 110 119",
|
|
"--border-light": "67 72 78",
|
|
"--accent": "0 144 255",
|
|
"--status-success": "61 214 140",
|
|
"--status-danger": "255 149 146",
|
|
"--status-warning": "255 202 22",
|
|
};
|
|
|
|
describe("buildTerminalTheme", () => {
|
|
it("maps theme tokens onto the xterm palette", () => {
|
|
const t = buildTerminalTheme((n) => vars[n] ?? "");
|
|
expect(t.background).toBe("#111113");
|
|
expect(t.foreground).toBe("#edeef0");
|
|
expect(t.cursor).toBe("#edeef0");
|
|
expect(t.selectionBackground).toBe("#43484e");
|
|
expect(t.red).toBe("#ff9592");
|
|
expect(t.green).toBe("#3dd68c");
|
|
expect(t.yellow).toBe("#ffca16");
|
|
expect(t.blue).toBe("#0090ff");
|
|
expect(t.black).toBe("#43484e");
|
|
expect(t.brightBlack).toBe("#696e77");
|
|
expect(t.brightWhite).toBe("#edeef0");
|
|
});
|
|
|
|
it("makes each bright twin lighter than its base colour", () => {
|
|
const t = buildTerminalTheme((n) => vars[n] ?? "");
|
|
const sum = (hex: string) =>
|
|
[1, 3, 5].reduce((a, i) => a + parseInt(hex.slice(i, i + 2), 16), 0);
|
|
for (const c of ["red", "green", "yellow", "blue", "magenta", "cyan"] as const) {
|
|
const base = t[c]!;
|
|
const bright = t[`bright${c[0]!.toUpperCase()}${c.slice(1)}` as keyof typeof t] as string;
|
|
expect(sum(bright)).toBeGreaterThan(sum(base));
|
|
}
|
|
});
|
|
|
|
it("leaves a colour unset when its variable is missing, so xterm keeps its default", () => {
|
|
const t = buildTerminalTheme(() => "");
|
|
expect(t.background).toBeUndefined();
|
|
expect(t.red).toBeUndefined();
|
|
});
|
|
});
|
|
|
|
describe("terminalThemeFor", () => {
|
|
it("resolves variables on a dark probe scoped to the theme id, then removes it", () => {
|
|
const style = document.createElement("style");
|
|
style.textContent = `.dark { --surface-0: 1 2 3; } .dark[data-theme="darcula"] { --surface-0: 30 31 32; }`;
|
|
document.head.appendChild(style);
|
|
try {
|
|
expect(terminalThemeFor("default").background).toBe("#010203");
|
|
expect(terminalThemeFor("darcula").background).toBe("#1e1f20");
|
|
expect(document.body.children).toHaveLength(0);
|
|
} finally {
|
|
style.remove();
|
|
}
|
|
});
|
|
});
|