← 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,
  };
}