Browse Source

refactor(dashboard): Extract shared theme colors to reduce duplication

- Create COLORS constant with named color tokens shared between themes
- Reduces SonarQube code duplication from 10.8% by consolidating
  repeated OKLCH values into single source of truth
- Makes color relationships between light/dark themes explicit

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Will Nahmens 4 days ago
parent
commit
5c4b63e91a
1 changed files with 91 additions and 62 deletions
  1. 91 62
      packages/dashboard/vite/vite-plugin-theme.ts

+ 91 - 62
packages/dashboard/vite/vite-plugin-theme.ts

@@ -1,5 +1,34 @@
 import { Plugin } from 'vite';
 import { Plugin } from 'vite';
 
 
+/**
+ * Shared color palette used across light and dark themes.
+ * Extracting these reduces duplication and makes theme relationships clearer.
+ */
+const COLORS = {
+    // Primary brand color
+    primary: 'oklch(0.7613 0.1503 231.1314)',
+    // Pure white/black variants
+    white: 'oklch(1.0000 0 0)',
+    nearWhite: 'oklch(0.9851 0 0)',
+    // Gray scale - light theme
+    lightForeground: 'oklch(0.2103 0.0059 285.8852)',
+    lightMuted: 'oklch(0.9674 0.0013 286.3752)',
+    lightMutedForeground: 'oklch(0.5517 0.0138 285.9385)',
+    lightBorder: 'oklch(0.9197 0.0040 286.3202)',
+    // Gray scale - dark theme
+    darkBackground: 'oklch(0.1408 0.0044 285.8229)',
+    darkCard: 'oklch(0.2103 0.0059 285.8852)',
+    darkMuted: 'oklch(0.2739 0.0055 286.0326)',
+    darkMutedForeground: 'oklch(0.7118 0.0129 286.0665)',
+    // Brand colors (shared)
+    brand: '#17c1ff',
+    brandLighter: '#e6f9ff',
+    brandDarker: '#0099ff',
+    // Fonts (shared)
+    fontSans: 'Inter, sans-serif',
+    fontMono: 'Geist Mono, monospace',
+} as const;
+
 type ThemeColors = {
 type ThemeColors = {
     background?: string;
     background?: string;
     foreground?: string;
     foreground?: string;
@@ -53,93 +82,93 @@ export interface ThemeVariables {
 
 
 const defaultVariables: ThemeVariables = {
 const defaultVariables: ThemeVariables = {
     light: {
     light: {
-        background: 'oklch(1.0000 0 0)',
-        foreground: 'oklch(0.2103 0.0059 285.8852)',
-        card: 'oklch(1.0000 0 0)',
-        'card-foreground': 'oklch(0.2103 0.0059 285.8852)',
-        popover: 'oklch(1.0000 0 0)',
-        'popover-foreground': 'oklch(0.2103 0.0059 285.8852)',
-        primary: 'oklch(0.7613 0.1503 231.1314)',
+        background: COLORS.white,
+        foreground: COLORS.lightForeground,
+        card: COLORS.white,
+        'card-foreground': COLORS.lightForeground,
+        popover: COLORS.white,
+        'popover-foreground': COLORS.lightForeground,
+        primary: COLORS.primary,
         'primary-foreground': 'oklch(0.261 0.043 218.379)',
         'primary-foreground': 'oklch(0.261 0.043 218.379)',
-        secondary: 'oklch(0.9674 0.0013 286.3752)',
-        'secondary-foreground': 'oklch(0.2103 0.0059 285.8852)',
-        muted: 'oklch(0.9674 0.0013 286.3752)',
-        'muted-foreground': 'oklch(0.5517 0.0138 285.9385)',
-        accent: 'oklch(0.9674 0.0013 286.3752)',
-        'accent-foreground': 'oklch(0.2103 0.0059 285.8852)',
+        secondary: COLORS.lightMuted,
+        'secondary-foreground': COLORS.lightForeground,
+        muted: COLORS.lightMuted,
+        'muted-foreground': COLORS.lightMutedForeground,
+        accent: COLORS.lightMuted,
+        'accent-foreground': COLORS.lightForeground,
         // L=0.60 ensures WCAG AA contrast ratio (4.5:1) against white backgrounds
         // L=0.60 ensures WCAG AA contrast ratio (4.5:1) against white backgrounds
         destructive: 'oklch(0.60 0.24 27.325)',
         destructive: 'oklch(0.60 0.24 27.325)',
-        'destructive-foreground': 'oklch(0.9851 0 0)',
+        'destructive-foreground': COLORS.nearWhite,
         success: 'hsl(99deg 67.25% 33.2%)',
         success: 'hsl(99deg 67.25% 33.2%)',
         'success-foreground': 'hsl(0 0% 98%)',
         'success-foreground': 'hsl(0 0% 98%)',
         'dev-mode': 'hsl(204, 76%, 62%)',
         'dev-mode': 'hsl(204, 76%, 62%)',
         'dev-mode-foreground': 'hsl(0 0% 98%)',
         'dev-mode-foreground': 'hsl(0 0% 98%)',
-        border: 'oklch(0.9197 0.0040 286.3202)',
-        input: 'oklch(0.9197 0.0040 286.3202)',
-        ring: 'oklch(0.7613 0.1503 231.1314)',
-        'chart-1': 'oklch(0.7613 0.1503 231.1314)',
+        border: COLORS.lightBorder,
+        input: COLORS.lightBorder,
+        ring: COLORS.primary,
+        'chart-1': COLORS.primary,
         'chart-2': 'oklch(0.5575 0.2525 302.3212)',
         'chart-2': 'oklch(0.5575 0.2525 302.3212)',
         'chart-3': 'oklch(0.5858 0.2220 17.5846)',
         'chart-3': 'oklch(0.5858 0.2220 17.5846)',
         'chart-4': 'oklch(0.6658 0.1574 58.3183)',
         'chart-4': 'oklch(0.6658 0.1574 58.3183)',
         'chart-5': 'oklch(0.6271 0.1699 149.2138)',
         'chart-5': 'oklch(0.6271 0.1699 149.2138)',
         radius: '0.375rem',
         radius: '0.375rem',
-        sidebar: 'oklch(0.9674 0.0013 286.3752)',
-        'sidebar-foreground': 'oklch(0.2103 0.0059 285.8852)',
-        'sidebar-primary': 'oklch(0.7613 0.1503 231.1314)',
-        'sidebar-primary-foreground': 'oklch(0.1408 0.0044 285.8229)',
-        'sidebar-accent': 'oklch(1.0000 0 0)',
-        'sidebar-accent-foreground': 'oklch(0.2103 0.0059 285.8852)',
-        'sidebar-border': 'oklch(0.9197 0.0040 286.3202)',
-        'sidebar-ring': 'oklch(0.7613 0.1503 231.1314)',
-        brand: '#17c1ff',
-        'brand-lighter': '#e6f9ff',
-        'brand-darker': '#0099ff',
-        'font-sans': 'Inter, sans-serif',
-        'font-mono': 'Geist Mono, monospace',
+        sidebar: COLORS.lightMuted,
+        'sidebar-foreground': COLORS.lightForeground,
+        'sidebar-primary': COLORS.primary,
+        'sidebar-primary-foreground': COLORS.darkBackground,
+        'sidebar-accent': COLORS.white,
+        'sidebar-accent-foreground': COLORS.lightForeground,
+        'sidebar-border': COLORS.lightBorder,
+        'sidebar-ring': COLORS.primary,
+        brand: COLORS.brand,
+        'brand-lighter': COLORS.brandLighter,
+        'brand-darker': COLORS.brandDarker,
+        'font-sans': COLORS.fontSans,
+        'font-mono': COLORS.fontMono,
     },
     },
     dark: {
     dark: {
-        background: 'oklch(0.1408 0.0044 285.8229)',
-        foreground: 'oklch(0.9851 0 0)',
-        card: 'oklch(0.2103 0.0059 285.8852)',
-        'card-foreground': 'oklch(0.9851 0 0)',
-        popover: 'oklch(0.2103 0.0059 285.8852)',
-        'popover-foreground': 'oklch(0.9851 0 0)',
-        primary: 'oklch(0.7613 0.1503 231.1314)',
-        'primary-foreground': 'oklch(0.1408 0.0044 285.8229)',
-        secondary: 'oklch(0.2739 0.0055 286.0326)',
-        'secondary-foreground': 'oklch(0.9851 0 0)',
-        muted: 'oklch(0.2739 0.0055 286.0326)',
-        'muted-foreground': 'oklch(0.7118 0.0129 286.0665)',
-        accent: 'oklch(0.2739 0.0055 286.0326)',
-        'accent-foreground': 'oklch(0.9851 0 0)',
+        background: COLORS.darkBackground,
+        foreground: COLORS.nearWhite,
+        card: COLORS.darkCard,
+        'card-foreground': COLORS.nearWhite,
+        popover: COLORS.darkCard,
+        'popover-foreground': COLORS.nearWhite,
+        primary: COLORS.primary,
+        'primary-foreground': COLORS.darkBackground,
+        secondary: COLORS.darkMuted,
+        'secondary-foreground': COLORS.nearWhite,
+        muted: COLORS.darkMuted,
+        'muted-foreground': COLORS.darkMutedForeground,
+        accent: COLORS.darkMuted,
+        'accent-foreground': COLORS.nearWhite,
         // L=0.75 ensures WCAG AA contrast ratio (4.5:1) against dark backgrounds
         // L=0.75 ensures WCAG AA contrast ratio (4.5:1) against dark backgrounds
         destructive: 'oklch(0.75 0.22 25)',
         destructive: 'oklch(0.75 0.22 25)',
-        'destructive-foreground': 'oklch(0.9851 0 0)',
+        'destructive-foreground': COLORS.nearWhite,
         success: 'hsl(100 76.42% 22.21%)',
         success: 'hsl(100 76.42% 22.21%)',
         'success-foreground': 'hsl(0 0% 98%)',
         'success-foreground': 'hsl(0 0% 98%)',
         'dev-mode': 'hsl(204, 86%, 53%)',
         'dev-mode': 'hsl(204, 86%, 53%)',
         'dev-mode-foreground': 'hsl(0 0% 98%)',
         'dev-mode-foreground': 'hsl(0 0% 98%)',
-        border: 'oklch(0.2739 0.0055 286.0326)',
-        input: 'oklch(0.2739 0.0055 286.0326)',
-        ring: 'oklch(0.7613 0.1503 231.1314)',
-        'chart-1': 'oklch(0.7613 0.1503 231.1314)',
+        border: COLORS.darkMuted,
+        input: COLORS.darkMuted,
+        ring: COLORS.primary,
+        'chart-1': COLORS.primary,
         'chart-2': 'oklch(0.6268 0.2325 303.9004)',
         'chart-2': 'oklch(0.6268 0.2325 303.9004)',
         'chart-3': 'oklch(0.6450 0.2154 16.4393)',
         'chart-3': 'oklch(0.6450 0.2154 16.4393)',
         'chart-4': 'oklch(0.7686 0.1647 70.0804)',
         'chart-4': 'oklch(0.7686 0.1647 70.0804)',
         'chart-5': 'oklch(0.7227 0.1920 149.5793)',
         'chart-5': 'oklch(0.7227 0.1920 149.5793)',
         sidebar: 'oklch(0.2 0 0)',
         sidebar: 'oklch(0.2 0 0)',
-        'sidebar-foreground': 'oklch(0.9851 0 0)',
-        'sidebar-primary': 'oklch(0.7613 0.1503 231.1314)',
-        'sidebar-primary-foreground': 'oklch(0.1408 0.0044 285.8229)',
-        'sidebar-accent': 'oklch(0.2739 0.0055 286.0326)',
-        'sidebar-accent-foreground': 'oklch(0.9851 0 0)',
-        'sidebar-border': 'oklch(0.2739 0.0055 286.0326)',
-        'sidebar-ring': 'oklch(0.7613 0.1503 231.1314)',
-        brand: '#17c1ff',
-        'brand-lighter': '#e6f9ff',
-        'brand-darker': '#0099ff',
-        'font-sans': 'Inter, sans-serif',
-        'font-mono': 'Geist Mono, monospace',
+        'sidebar-foreground': COLORS.nearWhite,
+        'sidebar-primary': COLORS.primary,
+        'sidebar-primary-foreground': COLORS.darkBackground,
+        'sidebar-accent': COLORS.darkMuted,
+        'sidebar-accent-foreground': COLORS.nearWhite,
+        'sidebar-border': COLORS.darkMuted,
+        'sidebar-ring': COLORS.primary,
+        brand: COLORS.brand,
+        'brand-lighter': COLORS.brandLighter,
+        'brand-darker': COLORS.brandDarker,
+        'font-sans': COLORS.fontSans,
+        'font-mono': COLORS.fontMono,
     },
     },
 };
 };