From 10374bb7a27bb86fded89c5ca7fbc4197796bb54 Mon Sep 17 00:00:00 2001 From: Austin Pickett Date: Mon, 29 Jun 2026 08:46:37 -0400 Subject: [PATCH] fix(web): theme terminal foreground and restore backdrop plugin slot Make Nous Blue terminal text readable without the inversion layer, re-mount the backdrop plugin slot, and drop unused backdrop CSS vars from theme apply. Co-authored-by: Cursor --- web/src/App.tsx | 7 ++++++ web/src/components/ThemeSwitcher.tsx | 6 ----- web/src/pages/ChatPage.tsx | 36 ++++++++++++++++------------ web/src/plugins/slots.ts | 3 ++- web/src/themes/context.tsx | 8 ++++--- web/src/themes/presets.ts | 1 + web/src/themes/types.ts | 22 +++++++---------- 7 files changed, 44 insertions(+), 39 deletions(-) diff --git a/web/src/App.tsx b/web/src/App.tsx index 419939329c3..9a599f66eb0 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -486,6 +486,13 @@ export default function App() { > +
+ +
+
({ ...TERMINAL_THEME_STATIC, background: terminalBg }), - [terminalBg], + () => buildTerminalTheme(terminalBg, terminalFg), + [terminalBg, terminalFg], ); // The dashboard keeps ChatPage mounted persistently so the PTY survives tab @@ -897,12 +903,12 @@ export default function ChatPage({ isActive = true }: { isActive?: boolean }) { }, [isActive]); // Keep the live xterm theme in sync when the active theme's terminal - // background changes (e.g. user switches to a custom YAML theme mid-session). + // colors change (e.g. user switches to a custom YAML theme mid-session). useEffect(() => { const term = termRef.current; if (!term) return; - term.options.theme = { ...TERMINAL_THEME_STATIC, background: terminalBg }; - }, [terminalBg]); + term.options.theme = terminalTheme; + }, [terminalTheme]); // Layout: // outer flex column — sits inside the dashboard's content area @@ -1065,7 +1071,7 @@ export default function ChatPage({ isActive = true }: { isActive?: boolean }) { "bottom-2 right-2 px-2 py-1 text-xs sm:bottom-3 sm:right-3 sm:px-2.5 sm:py-1.5", "lg:bottom-4 lg:right-4", )} - style={{ color: TERMINAL_THEME_STATIC.foreground }} + style={{ color: terminalFg }} > diff --git a/web/src/plugins/slots.ts b/web/src/plugins/slots.ts index 72d382bce75..f040a589a03 100644 --- a/web/src/plugins/slots.ts +++ b/web/src/plugins/slots.ts @@ -19,7 +19,8 @@ import React, { Fragment, useEffect, useState } from "react"; * these in their manifest's `slots` field get wired in automatically. * * Shell-wide slots: - * - `backdrop` — optional full-viewport background decoration + * - `backdrop` — optional full-viewport background decoration; + * mounted behind shell chrome at z-0 * - `header-left` — injected before the Hermes brand in the top bar * - `header-right` — injected before the theme/language switchers * - `header-banner` — injected below the top nav bar, full-width diff --git a/web/src/themes/context.tsx b/web/src/themes/context.tsx index 3cf2d97b48b..b991d8a4184 100644 --- a/web/src/themes/context.tsx +++ b/web/src/themes/context.tsx @@ -82,8 +82,6 @@ function paletteVars(palette: ThemePalette): Record { ...layerVars("background", palette.background), ...layerVars("midground", palette.midground), ...layerVars("foreground", palette.foreground), - "--warm-glow": palette.warmGlow, - "--noise-opacity-mul": String(palette.noiseOpacity), }; } @@ -391,11 +389,15 @@ function applyTheme(theme: DashboardTheme) { applyCustomCSS(theme.customCSS); applyLayoutVariant(theme.layoutVariant); - // Terminal background — read by ChatPage via useTheme(); also available as CSS var. + // Terminal colors — read by ChatPage via useTheme(); also available as CSS vars. root.style.setProperty( "--theme-terminal-background", theme.terminalBackground ?? "#000000", ); + root.style.setProperty( + "--theme-terminal-foreground", + theme.terminalForeground ?? "#f0e6d2", + ); // Re-assert the font override last: theme application just rewrote // --theme-font-sans/-display, so an active override has to win again. diff --git a/web/src/themes/presets.ts b/web/src/themes/presets.ts index 6ae7e9f94e2..fdf1593fe86 100644 --- a/web/src/themes/presets.ts +++ b/web/src/themes/presets.ts @@ -199,6 +199,7 @@ export const nousBlueTheme: DashboardTheme = { typography: DEFAULT_TYPOGRAPHY, layout: DEFAULT_LAYOUT, terminalBackground: "#f5f8fc", + terminalForeground: "#170d02", seriesColors: { inputTokenAccent: "#001934", outputTokenAccent: "#0053fd", diff --git a/web/src/themes/types.ts b/web/src/themes/types.ts index 8a1462c48e4..ebf9476c51b 100644 --- a/web/src/themes/types.ts +++ b/web/src/themes/types.ts @@ -80,7 +80,8 @@ export type ThemeLayoutVariant = "standard" | "cockpit" | "tiled"; * emitted as a CSS var (`--theme-asset-`). Plugin slots and * shell chrome may consume these via CSS. */ export interface ThemeAssets { - /** Full-viewport background image URL. */ + /** Full-viewport background image URL. Exposed as `--theme-asset-bg` for + * the `backdrop` plugin slot or theme `customCSS`. */ bg?: string; /** Hero render (Gundam, mascot, wallpaper) — for plugin sidebars/overlays. */ hero?: string; @@ -120,13 +121,7 @@ export interface ThemeComponentStyles { * `--series-input-token` / `--series-output-token` CSS vars consumed * inline by pages that render input-vs-output token flows. Themes can * omit either field to inherit the default token defined in - * `index.css` (Hermes-teal `#ffe6cb` for input, `#34d399` for output). - * - * Inverted-lens themes (e.g. Nous Blue) must pre-invert these hex - * values so they read as their intended visual color after the FG - * difference layer flips them (`out = 255 − channel`). E.g. to make - * output paint as Nous-blue `#0053FD` on screen, set - * `outputTokenAccent: "#FFAC02"` — the difference math reverses it. */ + * `index.css` (Hermes-teal `#ffe6cb` for input, `#34d399` for output). */ export interface ThemeSeriesColors { /** Input-tokens series accent (Analytics chart bars + table values). */ inputTokenAccent?: string; @@ -177,18 +172,17 @@ export interface DashboardTheme { /** Per-component CSS-var overrides. See `ThemeComponentStyles`. */ componentStyles?: ThemeComponentStyles; colorOverrides?: ThemeColorOverrides; - /** Data-series accent colors for Analytics/Models token charts. - * See `ThemeSeriesColors` for inversion-aware values. */ + /** Data-series accent colors for Analytics/Models token charts. */ seriesColors?: ThemeSeriesColors; - /** Explicit 3-color swatch override for the theme picker. Use when the - * palette's raw hex values don't reflect what users see on screen — - * e.g. inverted "lens" themes whose foreground-difference layer flips - * the authored colors to their visual complements. Order matches the + /** Explicit 3-color swatch override for the theme picker. Order matches the * default swatch cells: [background, midground, warmGlow]. */ swatchColors?: [string, string, string]; /** Background color for the embedded terminal pane (xterm.js). * Hex string. Defaults to `"#000000"` when absent. */ terminalBackground?: string; + /** Default text/cursor color for the embedded terminal pane (xterm.js). + * Hex string. Defaults to `"#f0e6d2"` when absent. */ + terminalForeground?: string; } /**