export interface Theme { id: string; name: string; description: string; author: string; isDark: boolean; colors: { bg: string; bgAlt: string; surface: string; surfaceHover: string; border: string; borderHover: string; text: string; textMuted: string; textInverse: string; primary: string; primaryHover: string; primaryMuted: string; secondary: string; secondaryHover: string; info: string; infoHover: string; infoMuted: string; neutral: string; neutralHover: string; neutralMuted: string; success: string; successMuted: string; successHover: string; warning: string; warningMuted: string; error: string; errorMuted: string; errorHover: string; link: string; linkVisited: string; overlay: string; fieldBg: string; onPrimary: string; }; } export const themes: Record = { neutral: { id: 'neutral', name: 'Neutral Dark', description: 'Default dark theme with neutral colors', author: 'Likwid', isDark: true, colors: { bg: '#0f0f0f', bgAlt: '#141414', surface: '#1a1a1a', surfaceHover: '#222222', border: '#2a2a2a', borderHover: '#3a3a3a', text: '#e0e0e0', textMuted: '#888888', textInverse: '#0f0f0f', primary: '#6366f1', primaryHover: '#4f46e5', primaryMuted: 'rgba(99, 102, 241, 0.15)', secondary: '#8b5cf6', secondaryHover: '#7c3aed', info: '#3b82f6', infoHover: '#2563eb', infoMuted: 'rgba(59, 130, 246, 0.15)', neutral: '#6b7280', neutralHover: '#4b5563', neutralMuted: 'rgba(107, 114, 128, 0.18)', success: '#22c55e', successMuted: 'rgba(34, 197, 94, 0.15)', successHover: '#16a34a', warning: '#f59e0b', warningMuted: 'rgba(245, 158, 11, 0.15)', error: '#ef4444', errorMuted: 'rgba(239, 68, 68, 0.15)', errorHover: '#dc2626', link: '#6366f1', linkVisited: '#8b5cf6', overlay: 'rgba(0, 0, 0, 0.8)', fieldBg: 'rgba(0, 0, 0, 0.25)', onPrimary: '#ffffff', }, }, 'breeze-light': { id: 'breeze-light', name: 'Breeze Light', description: 'Light theme inspired by the Breeze palette', author: 'Community', isDark: false, colors: { bg: '#eff0f1', bgAlt: '#e3e5e7', surface: '#fcfcfc', surfaceHover: '#f4f5f6', border: '#bdc3c7', borderHover: '#95a5a6', text: '#232629', textMuted: '#707d8a', textInverse: '#ffffff', primary: '#3daee9', primaryHover: '#2980b9', primaryMuted: 'rgba(61, 174, 233, 0.15)', secondary: '#1d99f3', secondaryHover: '#1a8fe8', info: '#3daee9', infoHover: '#2980b9', infoMuted: 'rgba(61, 174, 233, 0.15)', neutral: '#707d8a', neutralHover: '#4f5b66', neutralMuted: 'rgba(112, 125, 138, 0.2)', success: '#27ae60', successMuted: 'rgba(39, 174, 96, 0.15)', successHover: '#1f8a4d', warning: '#f67400', warningMuted: 'rgba(246, 116, 0, 0.15)', error: '#da4453', errorMuted: 'rgba(218, 68, 83, 0.15)', errorHover: '#b93a46', link: '#2980b9', linkVisited: '#9b59b6', overlay: 'rgba(0, 0, 0, 0.55)', fieldBg: '#f7f7f7', onPrimary: '#ffffff', }, }, 'breeze-dark': { id: 'breeze-dark', name: 'Breeze Dark', description: 'Dark theme inspired by the Breeze palette', author: 'Community', isDark: true, colors: { bg: '#1b1e20', bgAlt: '#121314', surface: '#232629', surfaceHover: '#2d3135', border: '#3d4349', borderHover: '#4d5459', text: '#fcfcfc', textMuted: '#a1a9b1', textInverse: '#232629', primary: '#3daee9', primaryHover: '#2980b9', primaryMuted: 'rgba(61, 174, 233, 0.2)', secondary: '#1d99f3', secondaryHover: '#1a8fe8', info: '#3daee9', infoHover: '#2980b9', infoMuted: 'rgba(61, 174, 233, 0.2)', neutral: '#a1a9b1', neutralHover: '#6b7280', neutralMuted: 'rgba(161, 169, 177, 0.2)', success: '#27ae60', successMuted: 'rgba(39, 174, 96, 0.2)', successHover: '#1f8a4d', warning: '#f67400', warningMuted: 'rgba(246, 116, 0, 0.2)', error: '#da4453', errorMuted: 'rgba(218, 68, 83, 0.2)', errorHover: '#b93a46', link: '#1d99f3', linkVisited: '#9b59b6', overlay: 'rgba(0, 0, 0, 0.8)', fieldBg: 'rgba(0, 0, 0, 0.25)', onPrimary: '#ffffff', }, }, opensuse: { id: 'opensuse', name: 'openSUSE', description: 'Theme based on openSUSE branding guidelines', author: 'openSUSE Community', isDark: true, colors: { bg: '#173f4f', bgAlt: '#1e4d5f', surface: '#21596e', surfaceHover: '#266a82', border: '#2d7a94', borderHover: '#3a8da7', text: '#f5f5f5', textMuted: '#a8c8d4', textInverse: '#173f4f', primary: '#73ba25', primaryHover: '#6aad20', primaryMuted: 'rgba(115, 186, 37, 0.2)', secondary: '#35b9ab', secondaryHover: '#2da89b', info: '#35b9ab', infoHover: '#2da89b', infoMuted: 'rgba(53, 185, 171, 0.2)', neutral: '#a8c8d4', neutralHover: '#7aa9b9', neutralMuted: 'rgba(168, 200, 212, 0.2)', success: '#73ba25', successMuted: 'rgba(115, 186, 37, 0.2)', successHover: '#5f9d1f', warning: '#f7a70d', warningMuted: 'rgba(247, 167, 13, 0.2)', error: '#e74c3c', errorMuted: 'rgba(231, 76, 60, 0.2)', errorHover: '#c0392b', link: '#73ba25', linkVisited: '#35b9ab', overlay: 'rgba(0, 0, 0, 0.75)', fieldBg: 'rgba(0, 0, 0, 0.18)', onPrimary: '#ffffff', }, }, }; export const DEFAULT_THEME = 'neutral'; export function getTheme(id: string): Theme { return themes[id] || themes[DEFAULT_THEME]; } export function getAllThemes(): Theme[] { return Object.values(themes); } export function applyTheme(theme: Theme): void { const root = document.documentElement; const { colors } = theme; root.style.setProperty('--color-bg', colors.bg); root.style.setProperty('--color-bg-alt', colors.bgAlt); root.style.setProperty('--color-surface', colors.surface); root.style.setProperty('--color-surface-hover', colors.surfaceHover); root.style.setProperty('--color-border', colors.border); root.style.setProperty('--color-border-hover', colors.borderHover); root.style.setProperty('--color-text', colors.text); root.style.setProperty('--color-text-muted', colors.textMuted); root.style.setProperty('--color-text-inverse', colors.textInverse); root.style.setProperty('--color-primary', colors.primary); root.style.setProperty('--color-primary-hover', colors.primaryHover); root.style.setProperty('--color-primary-muted', colors.primaryMuted); root.style.setProperty('--color-secondary', colors.secondary); root.style.setProperty('--color-secondary-hover', colors.secondaryHover); root.style.setProperty('--color-info', colors.info); root.style.setProperty('--color-info-hover', colors.infoHover); root.style.setProperty('--color-info-muted', colors.infoMuted); root.style.setProperty('--color-neutral', colors.neutral); root.style.setProperty('--color-neutral-hover', colors.neutralHover); root.style.setProperty('--color-neutral-muted', colors.neutralMuted); root.style.setProperty('--color-success', colors.success); root.style.setProperty('--color-success-muted', colors.successMuted); root.style.setProperty('--color-success-hover', colors.successHover); root.style.setProperty('--color-warning', colors.warning); root.style.setProperty('--color-warning-muted', colors.warningMuted); root.style.setProperty('--color-error', colors.error); root.style.setProperty('--color-error-muted', colors.errorMuted); root.style.setProperty('--color-error-hover', colors.errorHover); root.style.setProperty('--color-link', colors.link); root.style.setProperty('--color-link-visited', colors.linkVisited); root.style.setProperty('--color-overlay', colors.overlay); root.style.setProperty('--color-field-bg', colors.fieldBg); root.style.setProperty('--color-on-primary', colors.onPrimary); root.setAttribute('data-theme', theme.id); root.setAttribute('data-theme-mode', theme.isDark ? 'dark' : 'light'); } export function loadSavedTheme(): string { if (typeof localStorage !== 'undefined') { return localStorage.getItem('likwid-theme') || DEFAULT_THEME; } return DEFAULT_THEME; } export function saveTheme(themeId: string): void { if (typeof localStorage !== 'undefined') { localStorage.setItem('likwid-theme', themeId); } } export function initTheme(): void { const savedThemeId = loadSavedTheme(); const theme = getTheme(savedThemeId); applyTheme(theme); }