import { ColorTheme } from '../contexts/theme-data'; // Helper to convert hex to rgb values (e.g. "255, 255, 255") // Accepts #RRGGBB or #RGB const hexToRgbString = (hex: string): string => { // Remove # hex = hex.replace(/^#/, ''); // Parse let r = 0, g = 0, b = 0; if (hex.length === 3) { r = parseInt(hex[0] + hex[0], 16); g = parseInt(hex[1] + hex[1], 16); b = parseInt(hex[2] + hex[2], 16); } else if (hex.length === 6) { r = parseInt(hex.substring(0, 2), 16); g = parseInt(hex.substring(2, 4), 16); b = parseInt(hex.substring(4, 6), 16); } return `${r}, ${g}, ${b}`; }; const rgba = (hex: string, alpha: number = 1): string => { return `rgba(${hexToRgbString(hex)}, ${alpha})`; }; export const generateTokensCss = (theme: ColorTheme): string => { const { colors } = theme; return `/* ============================================ 🎨 TOKENS / VARIABLES (Generated by CLI) ============================================ */ :root, :root[data-theme="default"] { /* Brand Tokens - Source of Truth */ --xertica-primary: ${rgba(colors.primary)}; --xertica-dark: ${rgba(colors.sidebarDark)}; /* Approximating generic dark from sidebar dark if needed, or keeping static? */ /* Semantic Colors */ --background: rgba(255, 255, 255, 1); --foreground: rgba(9, 9, 11, 1); --card: rgba(255, 255, 255, 1); --card-foreground: rgba(9, 9, 11, 1); --popover: rgba(255, 255, 255, 1); --popover-foreground: rgba(9, 9, 11, 1); --primary: var(--xertica-primary); --primary-foreground: ${rgba(colors.primaryForeground)}; --primary-light: ${rgba(colors.primary, 0.15)}; --primary-light-foreground: ${rgba(colors.primary)}; --secondary: rgba(244, 244, 245, 1); --secondary-foreground: rgba(24, 24, 27, 1); --muted: rgba(244, 244, 245, 1); --muted-foreground: rgba(113, 113, 122, 1); --accent: rgba(244, 244, 245, 1); --accent-foreground: rgba(24, 24, 27, 1); --destructive: rgba(239, 68, 68, 1); --destructive-foreground: rgba(250, 250, 250, 1); /* Semantic Status Colors */ --success: rgba(5, 150, 105, 1); --success-foreground: rgba(250, 250, 250, 1); --info: rgba(37, 99, 235, 1); --info-foreground: rgba(250, 250, 250, 1); --warning: rgba(234, 179, 8, 1); --warning-foreground: rgba(28, 25, 23, 1); --border: rgba(228, 228, 231, 1); --input: rgba(244, 244, 245, 0.5); --input-background: rgba(244, 244, 245, 0.5); --ring: ${rgba(colors.primary, 0.5)}; /* Adjusted to match brand somewhat */ /* Sidebar */ --sidebar: ${rgba(colors.sidebarLight)}; --sidebar-foreground: ${colors.sidebarLight.toLowerCase() === '#ffffff' ? 'rgba(15, 23, 42, 1)' : 'rgba(250, 250, 250, 1)'}; --sidebar-primary: ${colors.sidebarLight.toLowerCase() === '#ffffff' ? rgba(colors.primary) : 'rgba(255, 255, 255, 1)'}; --sidebar-primary-foreground: ${colors.sidebarLight.toLowerCase() === '#ffffff' ? rgba(colors.primaryForeground) : rgba(colors.primary)}; /* Actually if sidebar is dark, primary item usually white? */ /* Replicating logic from Context roughly or sticking to safe defaults */ /* Context Logic: if !isSidebarLight: primary: #FFFFFF primaryFg: primary */ --sidebar-accent: ${rgba(colors.sidebarLight.toLowerCase() === '#ffffff' ? colors.primary : '#FFFFFF', 0.1)}; --sidebar-accent-foreground: ${colors.sidebarLight.toLowerCase() === '#ffffff' ? rgba(colors.primary) : '#FFFFFF'}; --sidebar-border: rgba(255, 255, 255, 0.1); --sidebar-ring: ${rgba(colors.primary, 0.5)}; /* Charts — vibrant, accessible, harmonious palette */ --chart-1: ${rgba(colors.chart1)}; --chart-2: ${rgba(colors.chart2)}; --chart-3: ${rgba(colors.chart3)}; --chart-4: ${rgba(colors.chart4)}; --chart-5: ${rgba(colors.chart5)}; --chart-6: rgba(168, 85, 247, 1); /* purple — extended palette */ --chart-7: rgba(20, 184, 166, 1); /* teal — extended palette */ --chart-8: rgba(251, 113, 133, 1); /* rose — extended palette */ /* Gradients */ --gradient-diagonal: linear-gradient(135deg, ${colors.gradientStart} 0%, ${colors.gradientEnd} 100%); /* Spacing & Radius */ --radius: 6px; --radius-button: 12px; --radius-card: 12px; --elevation-sm: 0px 0px 48px 0px rgba(0, 0, 0, 0.1); /* Typography */ --font-size: 16px; --text-h1: 2rem; --text-h2: 1.75rem; --text-h3: 1.5rem; --text-h4: 1.25rem; --text-base: 1rem; --text-p: 0.875rem; --text-label: 0.875rem; --text-small: 0.875rem; --text-xs: 0.75rem; --text-muted: 0.875rem; --text-stats: 2.25rem; --text-table-head: 1.25rem; --font-weight-regular: 400; --font-weight-medium: 500; --font-weight-semibold: 600; --font-weight-bold: 700; --font-weight-extrabold: 800; --spacing-1: 0.25rem; --spacing-2: 0.5rem; --spacing-3: 0.75rem; --spacing-4: 1rem; --spacing-5: 1.25rem; --spacing-6: 1.5rem; --spacing-8: 2rem; /* Calendar */ --cell-size: 2.5rem; --cell-radius: var(--radius); --calendar-caption-size: 15px; --calendar-weekday-size: 12px; --calendar-day-size: 14px; /* Toast - Success */ --toast-success-bg: rgba(220, 252, 231, 1); --toast-success-border: rgba(5, 150, 105, 1); --toast-success-icon: rgba(5, 150, 105, 1); /* Toast - Warning */ --toast-warning-bg: rgba(254, 249, 195, 1); --toast-warning-border: rgba(161, 98, 7, 1); --toast-warning-icon: rgba(161, 98, 7, 1); /* Toast - Info */ --toast-info-bg: rgba(219, 234, 254, 1); --toast-info-border: rgba(37, 99, 235, 1); --toast-info-icon: rgba(37, 99, 235, 1); /* Toast - Error */ --toast-error-bg: rgba(254, 226, 226, 1); --toast-error-border: rgba(239, 68, 68, 1); --toast-error-icon: rgba(239, 68, 68, 1); } :root[data-mode="dark"], .dark { /* Brand Tokens */ --xertica-primary: ${rgba(colors.primaryDarkMode)}; --primary: var(--xertica-primary); /* Semantic Colors */ --background: ${rgba(colors.darkBackground)}; --foreground: rgba(250, 250, 250, 1); --card: ${rgba(colors.darkCard)}; --card-foreground: rgba(250, 250, 250, 1); --popover: ${rgba(colors.darkCard)}; --popover-foreground: rgba(250, 250, 250, 1); --primary-foreground: ${rgba(colors.primaryForegroundDark)}; --primary-light: ${rgba(colors.primaryDarkMode, 0.15)}; --primary-light-foreground: ${rgba(colors.primaryDarkMode)}; --secondary: ${rgba(colors.darkMuted)}; --secondary-foreground: rgba(250, 250, 250, 1); --muted: ${rgba(colors.darkMuted)}; --muted-foreground: rgba(161, 161, 170, 1); --accent: ${rgba(colors.darkMuted)}; --accent-foreground: rgba(250, 250, 250, 1); --destructive: rgba(239, 68, 68, 1); --destructive-foreground: rgba(250, 250, 250, 1); /* Semantic Status Colors */ --success: rgba(34, 197, 94, 1); --success-foreground: rgba(5, 5, 5, 1); --info: rgba(96, 165, 250, 1); --info-foreground: rgba(5, 5, 5, 1); --warning: rgba(251, 191, 36, 1); --warning-foreground: rgba(5, 5, 5, 1); --border: ${rgba(colors.darkBorder)}; --input: ${rgba(colors.darkMuted, 0.5)}; --input-background: ${rgba(colors.darkMuted, 0.5)}; --ring: ${rgba(colors.primaryDarkMode, 0.5)}; --elevation-sm: 0px 0px 48px 0px rgba(0, 0, 0, 0.3); /* Charts — dark mode: slightly lighter/more saturated for contrast on dark bg */ --chart-1: ${rgba(colors.chart1)}; --chart-2: ${rgba(colors.chart2)}; --chart-3: ${rgba(colors.chart3)}; --chart-4: ${rgba(colors.chart4)}; --chart-5: ${rgba(colors.chart5)}; --chart-6: rgba(196, 132, 252, 1); /* purple lighter */ --chart-7: rgba(45, 212, 191, 1); /* teal lighter */ --chart-8: rgba(253, 164, 175, 1); /* rose lighter */ /* Sidebar */ --sidebar: ${rgba(colors.sidebarDark)}; --sidebar-foreground: rgba(250, 250, 250, 1); --sidebar-primary: rgba(255, 255, 255, 1); --sidebar-primary-foreground: ${rgba(colors.primary)}; --sidebar-accent: rgba(255, 255, 255, 0.08); --sidebar-accent-foreground: rgba(250, 250, 250, 1); --sidebar-border: ${rgba(colors.darkBorder)}; --sidebar-ring: ${rgba(colors.primaryDarkMode, 0.5)}; /* Gradients */ --gradient-diagonal: linear-gradient(135deg, ${colors.gradientStartDark} 0%, ${colors.gradientEndDark} 100%); /* Toast - Success */ --toast-success-bg: rgba(6, 78, 59, 1); --toast-success-border: rgba(34, 197, 94, 1); --toast-success-icon: rgba(34, 197, 94, 1); /* Toast - Warning */ --toast-warning-bg: rgba(113, 63, 18, 1); --toast-warning-border: rgba(251, 191, 36, 1); --toast-warning-icon: rgba(251, 191, 36, 1); /* Toast - Info */ --toast-info-bg: rgba(30, 58, 138, 1); --toast-info-border: rgba(96, 165, 250, 1); --toast-info-icon: rgba(96, 165, 250, 1); /* Toast - Error */ --toast-error-bg: rgba(127, 29, 29, 1); --toast-error-border: rgba(248, 113, 113, 1); --toast-error-icon: rgba(248, 113, 113, 1); } `; };