feat(FN-1214): add ember color theme

- Add ember theme to COLOR_THEMES array in types.ts
- Add ember theme CSS variables in styles.css
- Add ember theme swatch preview in ThemeSelector component
- Add ember to validThemes validation in index.html
- Add ThemeSelector tests for ember theme
This commit is contained in:
gsxdsm
2026-04-09 09:28:52 -07:00
parent f6b2a742c5
commit 914e80add3
5 changed files with 71 additions and 1 deletions

View File

@@ -54,6 +54,7 @@ export const COLOR_THEMES = [
"espresso",
"mars",
"poimandres",
"ember",
] as const;
export type ColorTheme = (typeof COLOR_THEMES)[number];

View File

@@ -59,6 +59,7 @@ const COLOR_THEMES: { value: ColorTheme; label: string; className: string }[] =
{ value: "espresso", label: "Espresso", className: "theme-swatch-espresso" },
{ value: "mars", label: "Mars", className: "theme-swatch-mars" },
{ value: "poimandres", label: "Poimandres", className: "theme-swatch-poimandres" },
{ value: "ember", label: "Ember", className: "theme-swatch-ember" },
];
/**

View File

@@ -115,6 +115,7 @@ describe("ThemeSelector", () => {
expect(screen.getByLabelText("Espresso theme")).toBeDefined();
expect(screen.getByLabelText("Mars theme")).toBeDefined();
expect(screen.getByLabelText("Poimandres theme")).toBeDefined();
expect(screen.getByLabelText("Ember theme")).toBeDefined();
});
it("marks current color theme as active", () => {
@@ -226,6 +227,9 @@ describe("ThemeSelector", () => {
fireEvent.click(screen.getByLabelText("Silver theme"));
expect(onColorThemeChange).toHaveBeenCalledWith("silver");
fireEvent.click(screen.getByLabelText("Ember theme"));
expect(onColorThemeChange).toHaveBeenCalledWith("ember");
});
it("displays Nord in preview when selected", () => {
@@ -397,6 +401,19 @@ describe("ThemeSelector", () => {
expect(screen.getByText(/Dark \/ Silver/)).toBeDefined();
});
it("displays Ember in preview when selected", () => {
render(
<ThemeSelector
themeMode="dark"
colorTheme="ember"
onThemeModeChange={vi.fn()}
onColorThemeChange={vi.fn()}
/>
);
expect(screen.getByText(/Dark \/ Ember/)).toBeDefined();
});
it("displays dramatic theme names in preview when selected", () => {
const { rerender } = render(
<ThemeSelector

View File

@@ -17,7 +17,7 @@
try {
var mode = localStorage.getItem('kb-dashboard-theme-mode') || 'dark';
var colorTheme = localStorage.getItem('kb-dashboard-color-theme') || 'default';
var validThemes = ['default', 'ocean', 'forest', 'sunset', 'zen', 'berry', 'high-contrast', 'industrial', 'monochrome', 'slate', 'ash', 'graphite', 'silver', 'solarized', 'factory', 'ayu', 'one-dark', 'nord', 'dracula', 'gruvbox', 'tokyo-night', 'catppuccin-mocha', 'github-dark', 'everforest', 'rose-pine', 'kanagawa', 'night-owl', 'palenight', 'monokai-pro', 'slime', 'brutalist', 'neon-city', 'parchment', 'terminal', 'glass', 'horizon', 'vitesse', 'outrun', 'snazzy', 'porple', 'espresso', 'mars', 'poimandres'];
var validThemes = ['default', 'ocean', 'forest', 'sunset', 'zen', 'berry', 'high-contrast', 'industrial', 'monochrome', 'slate', 'ash', 'graphite', 'silver', 'solarized', 'factory', 'ayu', 'one-dark', 'nord', 'dracula', 'gruvbox', 'tokyo-night', 'catppuccin-mocha', 'github-dark', 'everforest', 'rose-pine', 'kanagawa', 'night-owl', 'palenight', 'monokai-pro', 'slime', 'brutalist', 'neon-city', 'parchment', 'terminal', 'glass', 'horizon', 'vitesse', 'outrun', 'snazzy', 'porple', 'espresso', 'mars', 'poimandres', 'ember'];
if (!validThemes.includes(colorTheme)) {
colorTheme = 'default';
}

View File

@@ -9896,6 +9896,47 @@ html .column.drag-over * {
--accent: #606060;
}
/* EMBER - Dark graphite with orange accent */
[data-color-theme="ember"] {
--todo: #a0a0a0;
--in-progress: #b8b8b8;
--in-progress-rgb: 184, 184, 184;
--in-review: #d0d0d0;
--triage: #808080;
--done: #686868;
--color-success: #d0d0d0;
--color-error: #ff6b6b;
--cta-bg: #d4622a;
--cta-border: #e8773a;
--cta-text: #fff;
--cta-bg-hover: #e8773a;
--cta-border-hover: #f09050;
--cta-glow: 0 0 8px rgba(232, 119, 58, 0.3);
--logo-accent: #e8773a;
--color-info: #e8773a;
--accent: #e8773a;
}
[data-color-theme="ember"][data-theme="light"] {
--todo: #404040;
--in-progress: #606060;
--in-progress-rgb: 96, 96, 96;
--in-review: #606060;
--triage: #2a2a2a;
--done: #606060;
--color-success: #404040;
--color-error: #dc2626;
--cta-bg: #c05820;
--cta-border: #d4622a;
--cta-text: #fff;
--cta-bg-hover: #d4622a;
--cta-border-hover: #e07030;
--cta-glow: 0 0 8px rgba(192, 88, 32, 0.3);
--logo-accent: #d4622a;
--color-info: #c05820;
--accent: #d4622a;
}
/* SILVER - Light silvery grays */
[data-color-theme="silver"] {
--todo: #b0b0b0;
@@ -12836,6 +12877,11 @@ body[data-color-theme="terminal"][data-theme="light"]::before {
--surface: #27272a;
}
.theme-swatch-ember {
--bg: #18181b;
--surface: #27272a;
}
.theme-swatch-silver {
--bg: #27272a;
--surface: #3f3f46;
@@ -13127,6 +13173,11 @@ body[data-color-theme="terminal"][data-theme="light"]::before {
--surface: #f4f4f5;
}
[data-theme="light"] .theme-swatch-ember {
--bg: #fafafa;
--surface: #f4f4f5;
}
[data-theme="light"] .theme-swatch-silver {
--bg: #fafafa;
--surface: #f4f4f5;