From 7f210688177e9e0ce2943fb5176c700e37bcf673 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Thu, 30 Apr 2026 01:44:43 +0200 Subject: [PATCH] feat(ui-web): add teal-dark and teal-light themes and fix sap-horizon state colors --- ui/common/src/config/schema.ts | 8 +++- ui/web/README.md | 2 + ui/web/src/assets/themes/sap-horizon.css | 4 +- ui/web/src/assets/themes/teal-dark.css | 48 +++++++++++++++++++ ui/web/src/assets/themes/teal-light.css | 48 +++++++++++++++++++ ui/web/src/main.ts | 2 + .../unit/shared/composables/useTheme.test.ts | 6 ++- 7 files changed, 113 insertions(+), 5 deletions(-) create mode 100644 ui/web/src/assets/themes/teal-dark.css create mode 100644 ui/web/src/assets/themes/teal-light.css diff --git a/ui/common/src/config/schema.ts b/ui/common/src/config/schema.ts index 381967c0..615c7414 100644 --- a/ui/common/src/config/schema.ts +++ b/ui/common/src/config/schema.ts @@ -3,7 +3,13 @@ import { z } from 'zod' import { AuthenticationType, Protocol, ProtocolVersion } from '../types/UIProtocol.js' export const SKIN_IDS = ['classic', 'modern'] as const -export const THEME_IDS = ['catppuccin-latte', 'sap-horizon', 'tokyo-night-storm'] as const +export const THEME_IDS = [ + 'catppuccin-latte', + 'sap-horizon', + 'teal-dark', + 'teal-light', + 'tokyo-night-storm', +] as const export const authenticationConfigSchema = z .object({ diff --git a/ui/web/README.md b/ui/web/README.md index 17b64262..7d2bc8dc 100644 --- a/ui/web/README.md +++ b/ui/web/README.md @@ -142,6 +142,8 @@ Set `theme` in `config.json` to a filename (without `.css`) from `src/assets/the | Theme | Style | Source | | ------------------- | ----- | ---------------------------------------------------------------- | | `tokyo-night-storm` | Dark | [Tokyo Night](https://github.com/enkia/tokyo-night-vscode-theme) | +| `teal-dark` | Dark | Material Teal | +| `teal-light` | Light | Material Teal | | `catppuccin-latte` | Light | [Catppuccin](https://github.com/catppuccin/catppuccin) | | `sap-horizon` | Light | [SAP Horizon](https://github.com/SAP/theming-base-content) | diff --git a/ui/web/src/assets/themes/sap-horizon.css b/ui/web/src/assets/themes/sap-horizon.css index 7b59da0c..d52b4a5e 100644 --- a/ui/web/src/assets/themes/sap-horizon.css +++ b/ui/web/src/assets/themes/sap-horizon.css @@ -45,8 +45,8 @@ /* State colors (SAP Horizon palette) */ --color-state-ok: #256f3a; - --color-state-warn: #e9730c; - --color-state-err: #bb0000; + --color-state-warn: #e76500; + --color-state-err: #aa0808; --color-state-idle: var(--sap-label); color-scheme: light; diff --git a/ui/web/src/assets/themes/teal-dark.css b/ui/web/src/assets/themes/teal-dark.css new file mode 100644 index 00000000..898ad7d2 --- /dev/null +++ b/ui/web/src/assets/themes/teal-dark.css @@ -0,0 +1,48 @@ +/* Teal Dark */ + +:root[data-theme='teal-dark'] { + /* Palette */ + --td-bg-dark: #1a2027; + --td-bg-base: #1f2935; + --td-bg-raised: #263240; + --td-bg-hover: #2d3b4a; + --td-bg-active: #354454; + --td-fg-base: #b0bec5; + --td-fg-bright: #eceff1; + --td-fg-muted: #78909c; + --td-teal: #26a69a; + --td-teal-dim: #00897b; + --td-white: #ffffff; + + /* Semantic */ + --color-bg: var(--td-bg-base); + --color-bg-surface: var(--td-bg-dark); + --color-bg-input: var(--td-bg-dark); + --color-bg-hover: var(--td-bg-hover); + --color-bg-active: var(--td-bg-active); + --color-bg-header: var(--td-bg-dark); + --color-bg-caption: var(--td-bg-raised); + --color-bg-button: var(--td-teal-dim); + --color-bg-button-hover: color-mix(in srgb, var(--td-teal-dim) 67%, transparent); + --color-text: var(--td-fg-base); + --color-text-strong: var(--td-fg-bright); + --color-text-muted: var(--td-fg-muted); + --color-text-on-button: var(--td-white); + --color-primary: var(--td-teal); + --color-border: var(--td-bg-raised); + --color-border-row: var(--td-bg-hover); + --color-accent: var(--td-teal-dim); + --color-shadow-inset: rgba(0, 0, 0, 0.4); + + /* Surface hierarchy */ + --color-bg-raised: var(--td-bg-raised); + --color-bg-sunken: var(--td-bg-dark); + + /* State colors */ + --color-state-ok: #66bb6a; + --color-state-warn: #ffb300; + --color-state-err: #ef5350; + --color-state-idle: var(--td-fg-muted); + + color-scheme: dark; +} diff --git a/ui/web/src/assets/themes/teal-light.css b/ui/web/src/assets/themes/teal-light.css new file mode 100644 index 00000000..407b2e11 --- /dev/null +++ b/ui/web/src/assets/themes/teal-light.css @@ -0,0 +1,48 @@ +/* Teal Light */ + +:root[data-theme='teal-light'] { + /* Palette */ + --tl-bg: #f4f5f7; + --tl-bg-base: #ffffff; + --tl-bg-raised: #fafbfc; + --tl-bg-hover: #eef0f3; + --tl-bg-active: #e4e7eb; + --tl-fg-base: #3c4257; + --tl-fg-bright: #1a1f36; + --tl-fg-muted: #697386; + --tl-teal: #009688; + --tl-teal-dim: #00796b; + --tl-white: #ffffff; + + /* Semantic */ + --color-bg: var(--tl-bg); + --color-bg-surface: var(--tl-bg-base); + --color-bg-input: var(--tl-bg-base); + --color-bg-hover: var(--tl-bg-hover); + --color-bg-active: var(--tl-bg-active); + --color-bg-header: var(--tl-bg-raised); + --color-bg-caption: var(--tl-bg-raised); + --color-bg-button: var(--tl-teal-dim); + --color-bg-button-hover: color-mix(in srgb, var(--tl-teal-dim) 67%, transparent); + --color-text: var(--tl-fg-base); + --color-text-strong: var(--tl-fg-bright); + --color-text-muted: var(--tl-fg-muted); + --color-text-on-button: var(--tl-white); + --color-primary: var(--tl-teal); + --color-border: #e4e7eb; + --color-border-row: #eef0f3; + --color-accent: var(--tl-teal-dim); + --color-shadow-inset: rgba(16, 24, 40, 0.1); + + /* Surface hierarchy */ + --color-bg-raised: var(--tl-bg-hover); + --color-bg-sunken: var(--tl-bg-raised); + + /* State colors */ + --color-state-ok: #2e7d32; + --color-state-warn: #ef6c00; + --color-state-err: #c62828; + --color-state-idle: var(--tl-fg-muted); + + color-scheme: light; +} diff --git a/ui/web/src/main.ts b/ui/web/src/main.ts index 3b303dd7..ad2d0841 100644 --- a/ui/web/src/main.ts +++ b/ui/web/src/main.ts @@ -30,6 +30,8 @@ import './assets/shared.css' import './assets/themes/base.css' import './assets/themes/catppuccin-latte.css' import './assets/themes/sap-horizon.css' +import './assets/themes/teal-dark.css' +import './assets/themes/teal-light.css' import './assets/themes/tokyo-night-storm.css' const initializeApp = async (app: AppType, config: ConfigurationData): Promise => { diff --git a/ui/web/tests/unit/shared/composables/useTheme.test.ts b/ui/web/tests/unit/shared/composables/useTheme.test.ts index e3c213c0..91e12c4c 100644 --- a/ui/web/tests/unit/shared/composables/useTheme.test.ts +++ b/ui/web/tests/unit/shared/composables/useTheme.test.ts @@ -20,11 +20,13 @@ describe('useTheme', () => { expect(activeThemeId.value).toBe('tokyo-night-storm') }) - it('should return availableThemes with 3 entries', () => { + it('should return availableThemes with 5 entries', () => { const { availableThemes } = useTheme() - expect(availableThemes.length).toBe(3) + expect(availableThemes.length).toBe(5) expect(availableThemes).toContain('tokyo-night-storm') expect(availableThemes).toContain('catppuccin-latte') + expect(availableThemes).toContain('teal-dark') + expect(availableThemes).toContain('teal-light') expect(availableThemes).toContain('sap-horizon') }) -- 2.43.0