From bbd43b594831e4a0f606da276599e834287bf692 Mon Sep 17 00:00:00 2001 From: Linus Rath <139418639+rathlinus@users.noreply.github.com> Date: Wed, 3 Jun 2026 19:40:54 +0200 Subject: [PATCH] feat: render theme cards as a mini mailbox mockup from theme colors --- components/settings/themes-settings.tsx | 171 +++++++++++++++++++++++- 1 file changed, 165 insertions(+), 6 deletions(-) diff --git a/components/settings/themes-settings.tsx b/components/settings/themes-settings.tsx index ffd6a04f..c38cea84 100644 --- a/components/settings/themes-settings.tsx +++ b/components/settings/themes-settings.tsx @@ -1,10 +1,10 @@ 'use client'; -import { useEffect } from 'react'; +import { useEffect, useState } from 'react'; import { useThemeStore } from '@/stores/theme-store'; import { SettingsSection } from './settings-section'; import { cn } from '@/lib/utils'; -import { Check, Palette, Lock } from 'lucide-react'; +import { Check, Lock } from 'lucide-react'; import { toast } from '@/stores/toast-store'; import { usePolicyStore } from '@/stores/policy-store'; @@ -14,6 +14,18 @@ export function ThemesSettings() { const themePolicy = getThemePolicy(); const forcedThemeId = getForcedThemeId(installedThemes.map((theme) => theme.id)); + // Render each preview in the variant matching the app's current mode, and + // keep it in sync when the user toggles light/dark elsewhere. + const [isDark, setIsDark] = useState(false); + useEffect(() => { + const root = document.documentElement; + const update = () => setIsDark(root.classList.contains('dark')); + update(); + const obs = new MutationObserver(update); + obs.observe(root, { attributes: true, attributeFilter: ['class'] }); + return () => obs.disconnect(); + }, []); + // Filter out themes disabled by admin policy const visibleThemes = installedThemes.filter( theme => !isThemeDisabled(theme.id, !!theme.builtIn) @@ -61,6 +73,8 @@ export function ThemesSettings() { void; } -function ThemeCard({ name, author, preview, isActive, isDefault, isForceEnabled, disabled, variants, onActivate }: ThemeCardProps) { +function ThemeCard({ name, author, preview, css, isDark, isDefaultTheme, isActive, isDefault, isForceEnabled, disabled, variants, onActivate }: ThemeCardProps) { + const colors = resolveThemeColors({ css, variants, isDark: !!isDark, isDefaultTheme: !!isDefaultTheme }); return (