From 95bafe59b3e08f546c6ffe24103ba8988d870e58 Mon Sep 17 00:00:00 2001 From: Jeff Agapitos <233853744+jeffa-block@users.noreply.github.com> Date: Thu, 19 Mar 2026 21:58:53 +1100 Subject: [PATCH] feat(ui): add glass theme with native macOS vibrancy blur-through MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a 'Glass' theme option alongside Light, Dark, and System. On macOS, Electron's vibrancy: 'window' is already enabled in main.ts — this theme makes the CSS backgrounds semi-transparent so the native NSVisualEffectView blur layer shows through. On other platforms, backdrop-filter provides a CSS-only approximation. Changes: - theme-tokens.ts: add glassColorTokens with rgba() backgrounds - ThemeContext.tsx: extend ThemePreference to include 'glass' - ThemeSelector.tsx: add Glass button (Layers icon) - main.css: glass class with backdrop-filter and sidebar aliases - index.html: handle glass in pre-paint theme initialiser Implements #8008 --- ui/desktop/index.html | 11 ++- .../components/GooseSidebar/ThemeSelector.tsx | 20 +++++- ui/desktop/src/contexts/ThemeContext.tsx | 30 +++++--- ui/desktop/src/styles/main.css | 55 +++++++++++++++ ui/desktop/src/theme/theme-tokens.ts | 68 +++++++++++++++++-- 5 files changed, 166 insertions(+), 18 deletions(-) diff --git a/ui/desktop/index.html b/ui/desktop/index.html index 78a85db070c2..6547abc5d63f 100644 --- a/ui/desktop/index.html +++ b/ui/desktop/index.html @@ -13,13 +13,18 @@ const useSystemTheme = localStorage.getItem('use_system_theme') === 'true'; const systemPrefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; const savedTheme = localStorage.getItem('theme'); - const isDark = useSystemTheme ? systemPrefersDark : (savedTheme ? savedTheme === 'dark' : systemPrefersDark); + const isGlass = !useSystemTheme && savedTheme === 'glass'; + const isDark = useSystemTheme ? systemPrefersDark : (savedTheme ? savedTheme === 'dark' || savedTheme === 'glass' : systemPrefersDark); - if (isDark) { + if (isGlass) { + document.documentElement.classList.add('dark', 'glass'); + document.documentElement.style.colorScheme = 'dark'; + } else if (isDark) { document.documentElement.classList.add('dark'); + document.documentElement.classList.remove('glass'); document.documentElement.style.colorScheme = 'dark'; } else { - document.documentElement.classList.remove('dark'); + document.documentElement.classList.remove('dark', 'glass'); document.documentElement.style.colorScheme = 'light'; } } else { diff --git a/ui/desktop/src/components/GooseSidebar/ThemeSelector.tsx b/ui/desktop/src/components/GooseSidebar/ThemeSelector.tsx index f3783bd753e9..6a1770432a17 100644 --- a/ui/desktop/src/components/GooseSidebar/ThemeSelector.tsx +++ b/ui/desktop/src/components/GooseSidebar/ThemeSelector.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Moon, Sliders, Sun } from 'lucide-react'; +import { Layers, Moon, Sliders, Sun } from 'lucide-react'; import { Button } from '../ui/button'; import { useTheme } from '../../contexts/ThemeContext'; @@ -20,7 +20,7 @@ const ThemeSelector: React.FC = ({
{!hideTitle &&
Theme
}
+ + +