← back to Designer Wallcoverings
DW-Agents/dw-agents/agent-todays-highlights/theme-manager.js
599 lines
/**
* DW-Agents Theme Manager
* Modern Minimalist Theme System
*
* Provides consistent theming across all agents and web viewers
*/
const THEMES = {
'professional-dark': {
name: 'Professional Dark',
description: 'Dark grey background with white text for reduced eye strain',
// Color Palette
colors: {
// Primary colors - Bright blues for dark mode
primary: '#60a5fa', // Lighter blue for dark mode
primaryLight: '#93c5fd',
primaryDark: '#3b82f6',
// Secondary colors - Bright purple
secondary: '#a78bfa', // Lighter purple for dark mode
secondaryLight: '#c4b5fd',
secondaryDark: '#8b5cf6',
// Accent colors
accent: '#22d3ee', // Bright cyan accent
accentLight: '#67e8f9',
// Neutral colors - Dark greys
neutral50: '#1e293b',
neutral100: '#334155',
neutral200: '#475569',
neutral300: '#64748b',
neutral400: '#94a3b8',
neutral500: '#cbd5e1',
neutral600: '#e2e8f0',
neutral700: '#f1f5f9',
neutral800: '#f8fafc',
neutral900: '#ffffff',
// Semantic colors - Brighter for dark mode
success: '#34d399',
successLight: '#6ee7b7',
warning: '#fbbf24',
warningLight: '#fcd34d',
error: '#f87171',
errorLight: '#fca5a5',
info: '#60a5fa',
infoLight: '#93c5fd',
// Background colors - Dark greys
background: '#1e293b',
backgroundAlt: '#0f172a',
surface: '#334155',
surfaceAlt: '#475569',
// Text colors - Light for dark backgrounds
textPrimary: '#f1f5f9',
textSecondary: '#cbd5e1',
textTertiary: '#94a3b8',
textInverse: '#0f172a',
},
// Typography
typography: {
fontFamily: {
primary: "-apple-system, BlinkMacSystemFont, 'Inter', 'Segoe UI', 'Roboto', 'Helvetica Neue', sans-serif",
mono: "'JetBrains Mono', 'Fira Code', 'Monaco', 'Courier New', monospace",
display: "-apple-system, BlinkMacSystemFont, 'Inter', sans-serif",
},
fontSize: {
xs: '0.75rem',
sm: '0.875rem',
base: '1rem',
lg: '1.125rem',
xl: '1.25rem',
'2xl': '1.5rem',
'3xl': '1.875rem',
'4xl': '2.25rem',
},
fontWeight: {
normal: '400',
medium: '500',
semibold: '600',
bold: '700',
},
lineHeight: {
tight: '1.25',
normal: '1.5',
relaxed: '1.75',
},
},
spacing: {
xs: '0.25rem',
sm: '0.5rem',
md: '1rem',
lg: '1.5rem',
xl: '2rem',
'2xl': '3rem',
'3xl': '4rem',
'4xl': '6rem',
},
borderRadius: {
none: '0',
sm: '0.25rem',
md: '0.5rem',
lg: '0.75rem',
xl: '1rem',
'2xl': '1.5rem',
full: '9999px',
},
shadows: {
sm: '0 1px 2px 0 rgba(0, 0, 0, 0.3)',
md: '0 4px 6px -1px rgba(0, 0, 0, 0.4), 0 2px 4px -1px rgba(0, 0, 0, 0.3)',
lg: '0 10px 15px -3px rgba(0, 0, 0, 0.5), 0 4px 6px -2px rgba(0, 0, 0, 0.4)',
xl: '0 20px 25px -5px rgba(0, 0, 0, 0.6), 0 10px 10px -5px rgba(0, 0, 0, 0.5)',
'2xl': '0 25px 50px -12px rgba(0, 0, 0, 0.7)',
inner: 'inset 0 2px 4px 0 rgba(0, 0, 0, 0.4)',
none: 'none',
},
transitions: {
fast: '150ms cubic-bezier(0.4, 0, 0.2, 1)',
base: '300ms cubic-bezier(0.4, 0, 0.2, 1)',
slow: '500ms cubic-bezier(0.4, 0, 0.2, 1)',
},
components: {
button: {
primary: {
background: '#60a5fa',
backgroundHover: '#3b82f6',
color: '#0f172a',
padding: '0.75rem 1.5rem',
borderRadius: '0.5rem',
fontWeight: '600',
fontSize: '0.875rem',
boxShadow: '0 1px 2px 0 rgba(0, 0, 0, 0.3)',
transition: '300ms cubic-bezier(0.4, 0, 0.2, 1)',
},
secondary: {
background: '#475569',
backgroundHover: '#334155',
color: '#f1f5f9',
padding: '0.75rem 1.5rem',
borderRadius: '0.5rem',
fontWeight: '600',
fontSize: '0.875rem',
transition: '300ms cubic-bezier(0.4, 0, 0.2, 1)',
},
},
card: {
background: '#334155',
borderRadius: '0.75rem',
boxShadow: '0 1px 3px 0 rgba(0, 0, 0, 0.4), 0 1px 2px 0 rgba(0, 0, 0, 0.3)',
padding: '1.5rem',
border: '1px solid #475569',
},
header: {
background: 'linear-gradient(135deg, #60a5fa 0%, #a78bfa 100%)',
color: '#0f172a',
padding: '1.5rem 2rem',
boxShadow: '0 4px 6px -1px rgba(0, 0, 0, 0.4)',
borderRadius: '0.75rem',
},
input: {
background: '#475569',
border: '1px solid #64748b',
borderFocus: '2px solid #60a5fa',
borderRadius: '0.5rem',
padding: '0.75rem 1rem',
fontSize: '0.875rem',
color: '#f1f5f9',
transition: '150ms cubic-bezier(0.4, 0, 0.2, 1)',
},
},
},
'modern-minimalist': {
name: 'Modern Minimalist',
description: 'Clean, professional design with subtle colors and generous spacing',
// Color Palette
colors: {
// Primary colors - Cool, professional blues
primary: '#2563eb', // Modern blue
primaryLight: '#3b82f6',
primaryDark: '#1e40af',
// Secondary colors - Elegant purple
secondary: '#7c3aed', // Modern purple
secondaryLight: '#8b5cf6',
secondaryDark: '#6d28d9',
// Accent colors
accent: '#06b6d4', // Cyan accent
accentLight: '#22d3ee',
// Neutral colors - Minimal, clean grays
neutral50: '#f8fafc',
neutral100: '#f1f5f9',
neutral200: '#e2e8f0',
neutral300: '#cbd5e1',
neutral400: '#94a3b8',
neutral500: '#64748b',
neutral600: '#475569',
neutral700: '#334155',
neutral800: '#1e293b',
neutral900: '#0f172a',
// Semantic colors
success: '#10b981',
successLight: '#34d399',
warning: '#f59e0b',
warningLight: '#fbbf24',
error: '#ef4444',
errorLight: '#f87171',
info: '#3b82f6',
infoLight: '#60a5fa',
// Background colors
background: '#ffffff',
backgroundAlt: '#f8fafc',
surface: '#ffffff',
surfaceAlt: '#f1f5f9',
// Text colors
textPrimary: '#0f172a',
textSecondary: '#475569',
textTertiary: '#94a3b8',
textInverse: '#ffffff',
},
// Typography
typography: {
fontFamily: {
primary: "-apple-system, BlinkMacSystemFont, 'Inter', 'Segoe UI', 'Roboto', 'Helvetica Neue', sans-serif",
mono: "'JetBrains Mono', 'Fira Code', 'Monaco', 'Courier New', monospace",
display: "-apple-system, BlinkMacSystemFont, 'Inter', sans-serif",
},
fontSize: {
xs: '0.75rem', // 12px
sm: '0.875rem', // 14px
base: '1rem', // 16px
lg: '1.125rem', // 18px
xl: '1.25rem', // 20px
'2xl': '1.5rem', // 24px
'3xl': '1.875rem',// 30px
'4xl': '2.25rem', // 36px
},
fontWeight: {
normal: '400',
medium: '500',
semibold: '600',
bold: '700',
},
lineHeight: {
tight: '1.25',
normal: '1.5',
relaxed: '1.75',
},
},
// Spacing - Generous, minimal
spacing: {
xs: '0.25rem', // 4px
sm: '0.5rem', // 8px
md: '1rem', // 16px
lg: '1.5rem', // 24px
xl: '2rem', // 32px
'2xl': '3rem', // 48px
'3xl': '4rem', // 64px
'4xl': '6rem', // 96px
},
// Border Radius - Soft, modern curves
borderRadius: {
none: '0',
sm: '0.25rem', // 4px
md: '0.5rem', // 8px
lg: '0.75rem', // 12px
xl: '1rem', // 16px
'2xl': '1.5rem', // 24px
full: '9999px',
},
// Shadows - Subtle, layered
shadows: {
sm: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
md: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
lg: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
xl: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
'2xl': '0 25px 50px -12px rgba(0, 0, 0, 0.25)',
inner: 'inset 0 2px 4px 0 rgba(0, 0, 0, 0.06)',
none: 'none',
},
// Transitions
transitions: {
fast: '150ms cubic-bezier(0.4, 0, 0.2, 1)',
base: '300ms cubic-bezier(0.4, 0, 0.2, 1)',
slow: '500ms cubic-bezier(0.4, 0, 0.2, 1)',
},
// Component-specific styles
components: {
button: {
primary: {
background: '#2563eb',
backgroundHover: '#1e40af',
color: '#ffffff',
padding: '0.75rem 1.5rem',
borderRadius: '0.5rem',
fontWeight: '600',
fontSize: '0.875rem',
boxShadow: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
transition: '300ms cubic-bezier(0.4, 0, 0.2, 1)',
},
secondary: {
background: '#f1f5f9',
backgroundHover: '#e2e8f0',
color: '#334155',
padding: '0.75rem 1.5rem',
borderRadius: '0.5rem',
fontWeight: '600',
fontSize: '0.875rem',
transition: '300ms cubic-bezier(0.4, 0, 0.2, 1)',
},
},
card: {
background: '#ffffff',
borderRadius: '0.75rem',
boxShadow: '0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)',
padding: '1.5rem',
border: '1px solid #e2e8f0',
},
header: {
background: 'linear-gradient(135deg, #2563eb 0%, #7c3aed 100%)',
color: '#ffffff',
padding: '1.5rem 2rem',
boxShadow: '0 4px 6px -1px rgba(0, 0, 0, 0.1)',
borderRadius: '0.75rem',
},
input: {
background: '#ffffff',
border: '1px solid #cbd5e1',
borderFocus: '2px solid #2563eb',
borderRadius: '0.5rem',
padding: '0.75rem 1rem',
fontSize: '0.875rem',
color: '#0f172a',
transition: '150ms cubic-bezier(0.4, 0, 0.2, 1)',
},
},
},
};
/**
* Get theme by name
*/
function getTheme(themeName = 'modern-minimalist') {
return THEMES[themeName] || THEMES['modern-minimalist'];
}
/**
* Generate CSS variables from theme
*/
function generateCSSVariables(themeName = 'modern-minimalist') {
const theme = getTheme(themeName);
let css = ':root {\n';
// Colors
Object.entries(theme.colors).forEach(([key, value]) => {
const cssVar = key.replace(/([A-Z])/g, '-$1').toLowerCase();
css += ` --color-${cssVar}: ${value};\n`;
});
// Typography
Object.entries(theme.typography.fontSize).forEach(([key, value]) => {
css += ` --font-size-${key}: ${value};\n`;
});
Object.entries(theme.typography.fontWeight).forEach(([key, value]) => {
css += ` --font-weight-${key}: ${value};\n`;
});
css += ` --font-primary: ${theme.typography.fontFamily.primary};\n`;
css += ` --font-mono: ${theme.typography.fontFamily.mono};\n`;
// Spacing
Object.entries(theme.spacing).forEach(([key, value]) => {
css += ` --spacing-${key}: ${value};\n`;
});
// Border Radius
Object.entries(theme.borderRadius).forEach(([key, value]) => {
css += ` --radius-${key}: ${value};\n`;
});
// Shadows
Object.entries(theme.shadows).forEach(([key, value]) => {
css += ` --shadow-${key}: ${value};\n`;
});
// Transitions
Object.entries(theme.transitions).forEach(([key, value]) => {
css += ` --transition-${key}: ${value};\n`;
});
css += '}\n';
return css;
}
/**
* Generate inline styles for HTML injection
*/
function getInlineThemeStyles(themeName = 'modern-minimalist') {
const theme = getTheme(themeName);
return `
<style>
${generateCSSVariables(themeName)}
* {
box-sizing: border-box;
}
body {
font-family: ${theme.typography.fontFamily.primary};
font-size: ${theme.typography.fontSize.base};
line-height: ${theme.typography.lineHeight.normal};
color: ${theme.colors.textPrimary};
background: ${theme.colors.backgroundAlt};
margin: 0;
padding: 0;
}
/* Modern Minimalist Utility Classes */
.btn-primary {
background: ${theme.components.button.primary.background};
color: ${theme.components.button.primary.color};
padding: ${theme.components.button.primary.padding};
border: none;
border-radius: ${theme.components.button.primary.borderRadius};
font-weight: ${theme.components.button.primary.fontWeight};
font-size: ${theme.components.button.primary.fontSize};
cursor: pointer;
transition: ${theme.components.button.primary.transition};
box-shadow: ${theme.components.button.primary.boxShadow};
}
.btn-primary:hover {
background: ${theme.components.button.primary.backgroundHover};
transform: translateY(-1px);
box-shadow: ${theme.shadows.md};
}
.btn-secondary {
background: ${theme.components.button.secondary.background};
color: ${theme.components.button.secondary.color};
padding: ${theme.components.button.secondary.padding};
border: none;
border-radius: ${theme.components.button.secondary.borderRadius};
font-weight: ${theme.components.button.secondary.fontWeight};
font-size: ${theme.components.button.secondary.fontSize};
cursor: pointer;
transition: ${theme.components.button.secondary.transition};
}
.btn-secondary:hover {
background: ${theme.components.button.secondary.backgroundHover};
}
.card {
background: ${theme.components.card.background};
border-radius: ${theme.components.card.borderRadius};
box-shadow: ${theme.components.card.boxShadow};
padding: ${theme.components.card.padding};
border: ${theme.components.card.border};
}
.card:hover {
box-shadow: ${theme.shadows.lg};
transform: translateY(-2px);
transition: all ${theme.transitions.base};
}
.header {
background: ${theme.components.header.background};
color: ${theme.components.header.color};
padding: ${theme.components.header.padding};
box-shadow: ${theme.components.header.boxShadow};
border-radius: ${theme.components.header.borderRadius};
}
input, textarea, select {
background: ${theme.components.input.background};
border: ${theme.components.input.border};
border-radius: ${theme.components.input.borderRadius};
padding: ${theme.components.input.padding};
font-size: ${theme.components.input.fontSize};
color: ${theme.components.input.color};
transition: ${theme.components.input.transition};
font-family: inherit;
}
input:focus, textarea:focus, select:focus {
outline: none;
border: ${theme.components.input.borderFocus};
box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
}
/* Status badges */
.badge {
display: inline-block;
padding: 0.25rem 0.75rem;
border-radius: ${theme.borderRadius.full};
font-size: ${theme.typography.fontSize.sm};
font-weight: ${theme.typography.fontWeight.semibold};
}
.badge-success {
background: ${theme.colors.success};
color: white;
}
.badge-warning {
background: ${theme.colors.warning};
color: white;
}
.badge-error {
background: ${theme.colors.error};
color: white;
}
.badge-info {
background: ${theme.colors.info};
color: white;
}
/* Grid layouts */
.grid {
display: grid;
gap: ${theme.spacing.lg};
}
.grid-2 { grid-template-columns: repeat(2, 1fr); }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 768px) {
.grid-2, .grid-3, .grid-4 {
grid-template-columns: 1fr;
}
}
/* Typography helpers */
.text-primary { color: ${theme.colors.primary}; }
.text-secondary { color: ${theme.colors.textSecondary}; }
.text-muted { color: ${theme.colors.textTertiary}; }
h1, h2, h3, h4, h5, h6 {
font-weight: ${theme.typography.fontWeight.semibold};
color: ${theme.colors.textPrimary};
margin-top: 0;
}
h1 { font-size: ${theme.typography.fontSize['3xl']}; }
h2 { font-size: ${theme.typography.fontSize['2xl']}; }
h3 { font-size: ${theme.typography.fontSize.xl}; }
h4 { font-size: ${theme.typography.fontSize.lg}; }
</style>
`;
}
/**
* Get theme configuration as JSON
*/
function getThemeConfig(themeName = 'modern-minimalist') {
return JSON.stringify(getTheme(themeName), null, 2);
}
// Export for Node.js
if (typeof module !== 'undefined' && module.exports) {
module.exports = {
THEMES,
getTheme,
generateCSSVariables,
getInlineThemeStyles,
getThemeConfig,
};
}