/** * KodexaLabs Unified Design Tokens * Single source of truth for all design tokens across the system * * @module @kodexalabs/design-tokens * @author KodexaLabs * @version 1.0.0 */ /** * Color token structure with HSL support for runtime manipulation */ export interface ColorToken { /** Hue value (0-360) */ h: number; /** Saturation percentage */ s: string; /** Lightness percentage */ l: string; /** Computed HSL color string */ hsl: string; /** RGB color string for compatibility */ rgb: string; /** Hex color string */ hex: string; } /** * Complete design token system interface */ export interface DesignTokens { color: { // Primary brand colors brand: { /** Base workspace background - pure black */ background: ColorToken; /** Primary foreground for text and UI on black */ foreground: ColorToken; /** Kodexa white accent */ white: ColorToken; /** High-contrast white for active states */ whiteStrong: ColorToken; /** Success signal */ success: ColorToken; /** Muted neutral for secondary content */ muted: ColorToken; /** Logo gradient start */ logoPrimary: ColorToken; /** Logo gradient end */ logoSecondary: ColorToken; }; // Semantic colors (light theme) semantic: { background: string; foreground: string; surface: string; elev1: string; elev2: string; text: string; textMuted: string; textSubtle: string; border: string; borderSubtle: string; overlay: string; // New opacity-based surface tokens surfaceOverlay: string; overlayDark: string; textPrimary: string; textMutedLight: string; textSubtleLight: string; progressTrack: string; // Dark workspace background workspaceDark: string; // New scrollbar tokens scrollbarThumb: string; scrollbarThumbHover: string; // New card token cardDark: string; }; // Tailwind-compatible semantic colors ui: { card: string; cardForeground: string; popover: string; popoverForeground: string; primary: string; primaryForeground: string; secondary: string; secondaryForeground: string; muted: string; mutedForeground: string; accent: string; accentForeground: string; destructive: string; destructiveForeground: string; success: string; successForeground: string; warning: string; warningForeground: string; info: string; infoForeground: string; input: string; ring: string; }; // Neutral grayscale gray: { 50: string; 100: string; 200: string; 300: string; 400: string; 500: string; 600: string; 700: string; 800: string; 900: string; 950: string; // Additional semantic gray tokens textDark: string; textLight: string; accentPrimary: string; accentHover: string; accentDark: string; accentDarkHover: string; }; // Chart colors chart: { 1: string; 2: string; 3: string; 4: string; 5: string; }; }; typography: { // Font families fontFamily: { sans: string; mono: string; display: string; heading: string; body: string; }; // Fluid type scale (clamp-based) fontSize: { micro: string; // step--2 caption: string; // step--1 body: string; // step-0 subhead: string; // step-1 headline: string; // step-2 title: string; // step-3 display: string; // step-4 hero: string; // step-5 }; // Font weights fontWeight: { regular: number; medium: number; semibold: number; bold: number; black: number; thin: number; }; // Line heights lineHeight: { tight: number; snug: number; normal: number; relaxed: number; loose: number; }; // Letter spacing letterSpacing: { tighter: string; tight: string; normal: string; wide: string; wider: string; }; }; // Spacing scale (Rule of 8 + fine-grained) spacing: { 0: string; 0.5: string; // 2px 1: string; // 4px 1.5: string; // 6px 2: string; // 8px 2.5: string; // 10px 3: string; // 12px 3.5: string; // 14px 4: string; // 16px 5: string; // 20px 6: string; // 24px 7: string; // 28px 8: string; // 32px 9: string; // 36px 10: string; // 40px 12: string; // 48px 14: string; // 56px 16: string; // 64px 20: string; // 80px 24: string; // 96px 32: string; // 128px }; // Border radius radius: { none: string; xs: string; sm: string; md: string; lg: string; xl: string; "2xl": string; "3xl": string; round: string; circle: string; }; // Shadows shadow: { xs: string; sm: string; md: string; lg: string; xl: string; "2xl": string; inner: string; glow: string; glowStrong: string; shadowCardHover: string; shadowElevated: string; }; // Motion & animation motion: { // Easing functions easing: { standard: string; emphasized: string; decelerate: string; accelerate: string; sharp: string; }; // Durations duration: { instant: string; fast: string; base: string; slow: string; slower: string; }; }; // Layout layout: { container: { xs: string; sm: string; md: string; lg: string; xl: string; "2xl": string; }; measure: string; }; // Border widths borderWidth: { thin: string; base: string; thick: string; }; // Z-index layers zIndex: { bg: number; base: number; content: number; dropdown: number; sticky: number; overlay: number; modal: number; popover: number; tooltip: number; toast: number; }; } /** * Helper function to create color tokens */ function createColorToken(h: number, s: string, l: string, hex: string): ColorToken { const hsl = `hsl(${h} ${s} ${l})`; // Convert HSL to RGB for compatibility const hNum = h / 360; const sNum = parseInt(s) / 100; const lNum = parseInt(l) / 100; let r: number, g: number, b: number; if (sNum === 0) { r = g = b = lNum; } else { const hue2rgb = (p: number, q: number, t: number): number => { if (t < 0) t += 1; if (t > 1) t -= 1; if (t < 1 / 6) return p + (q - p) * 6 * t; if (t < 1 / 2) return q; if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; return p; }; const q = lNum < 0.5 ? lNum * (1 + sNum) : lNum + sNum - lNum * sNum; const p = 2 * lNum - q; r = hue2rgb(p, q, hNum + 1 / 3); g = hue2rgb(p, q, hNum); b = hue2rgb(p, q, hNum - 1 / 3); } const rgb = `rgb(${Math.round(r * 255)} ${Math.round(g * 255)} ${Math.round(b * 255)})`; return { h, s, l, hsl, rgb, hex }; } /** * Default design tokens (light theme) */ export const designTokens: DesignTokens = { color: { brand: { background: createColorToken(0, "0%", "0%", "#000000"), foreground: createColorToken(0, "0%", "100%", "#ffffff"), white: createColorToken(0, "0%", "100%", "#ffffff"), whiteStrong: createColorToken(0, "0%", "90%", "#e5e5e5"), success: createColorToken(87, "100%", "68%", "#b5ff5c"), muted: createColorToken(220, "4%", "56%", "#8a8d93"), logoPrimary: createColorToken(0, "0%", "100%", "#ffffff"), logoSecondary: createColorToken(0, "0%", "90%", "#e5e5e5"), }, semantic: { background: "hsl(0 0% 0%)", foreground: "hsl(0 0% 100%)", surface: "hsl(0 0% 7%)", elev1: "hsl(0 0% 10%)", elev2: "hsl(0 0% 13%)", text: "hsl(0 0% 100%)", textMuted: "hsl(0 0% 54%)", textSubtle: "hsl(0 0% 40%)", border: "hsl(0 0% 23%)", borderSubtle: "hsl(0 0% 15%)", overlay: "hsla(0 0% 0% / 0.7)", // New opacity-based surface tokens for slider components surfaceOverlay: "rgba(7, 7, 8, 0.72)", overlayDark: "rgba(0, 0, 0, 0.35)", textPrimary: "rgba(255, 255, 255, 0.92)", textMutedLight: "rgba(255, 255, 255, 0.56)", textSubtleLight: "rgba(255, 255, 255, 0.78)", progressTrack: "rgba(255, 255, 255, 0.24)", // Dark workspace background workspaceDark: "#060606", // New scrollbar tokens scrollbarThumb: "hsl(0 0% 40%)", scrollbarThumbHover: "hsl(0 0% 53%)", // New card token cardDark: "hsl(0 0% 6%)", }, ui: { card: "hsl(0 0% 7%)", cardForeground: "hsl(0 0% 100%)", popover: "hsl(0 0% 9%)", popoverForeground: "hsl(0 0% 100%)", primary: "hsl(0 0% 100%)", primaryForeground: "hsl(0 0% 100%)", secondary: "hsl(0 0% 18%)", secondaryForeground: "hsl(0 0% 96%)", muted: "hsl(0 0% 35%)", mutedForeground: "hsl(0 0% 78%)", accent: "hsl(243 100% 69%)", accentForeground: "hsl(0 0% 100%)", destructive: "hsl(0 84% 58%)", destructiveForeground: "hsl(0 0% 100%)", success: "hsl(87 100% 68%)", successForeground: "hsl(0 0% 12%)", warning: "hsl(45 100% 52%)", warningForeground: "hsl(0 0% 7%)", info: "hsl(243 100% 69%)", infoForeground: "hsl(0 0% 100%)", input: "hsl(0 0% 18%)", ring: "hsl(0 0% 100%)", }, gray: { 50: "#F5F6F8", // Light gray background 100: "#E5E7EB", // Gray background 200: "#B0B3B8", // Gray panel 300: "hsl(0 0% 13%)", 400: "hsl(0 0% 15%)", 500: "hsl(0 0% 17%)", 600: "hsl(0 0% 18%)", 700: "hsl(0 0% 20%)", 800: "#22232A", // Dark gray background 900: "#181920", // Darker gray background 950: "hsl(0 0% 5%)", // Additional semantic gray tokens textDark: "#222327", // Dark text on light textLight: "#787A80", // Muted text accentPrimary: "#1A73E8", // Blue accent accentHover: "#185eca", // Blue accent hover accentDark: "#61a0ff", // Dark theme accent accentDarkHover: "#3d73bf", // Dark theme accent hover }, chart: { 1: "hsl(0 0% 70%)", 2: "hsl(243 100% 69%)", 3: "hsl(259 91% 61%)", 4: "hsl(87 100% 68%)", 5: "hsl(0 0% 56%)", }, }, typography: { fontFamily: { sans: 'Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif', mono: 'SF Mono, Monaco, Inconsolata, Roboto Mono, Menlo, Consolas, "Liberation Mono", monospace', display: "Power Grotesk, Inter, ui-sans-serif, system-ui, sans-serif", heading: "Plus Jakarta Sans, Inter, ui-sans-serif, system-ui, sans-serif", body: "Inter, ui-sans-serif, system-ui, sans-serif", }, fontSize: { micro: "clamp(0.70rem, 0.72rem + -0.02vw, 0.69rem)", caption: "clamp(0.84rem, 0.83rem + 0.05vw, 0.88rem)", body: "clamp(1.00rem, 0.97rem + 0.16vw, 1.10rem)", subhead: "clamp(1.20rem, 1.12rem + 0.37vw, 1.38rem)", headline: "clamp(1.44rem, 1.28rem + 0.70vw, 1.72rem)", title: "clamp(1.73rem, 1.47rem + 1.19vw, 2.15rem)", display: "clamp(2.07rem, 1.68rem + 1.90vw, 2.69rem)", hero: "clamp(2.49rem, 1.92rem + 2.92vw, 3.36rem)", }, fontWeight: { regular: 400, medium: 500, semibold: 600, bold: 700, black: 900, thin: 200, }, lineHeight: { tight: 1.1, snug: 1.3, normal: 1.6, relaxed: 1.8, loose: 2.0, }, letterSpacing: { tighter: "-0.02em", tight: "-0.01em", normal: "0", wide: "0.02em", wider: "0.04em", }, }, spacing: { 0: "0", 0.5: "0.125rem", // 2px 1: "0.25rem", // 4px 1.5: "0.375rem", // 6px 2: "0.5rem", // 8px 2.5: "0.625rem", // 10px 3: "0.75rem", // 12px 3.5: "0.875rem", // 14px 4: "1rem", // 16px 5: "1.25rem", // 20px 6: "1.5rem", // 24px 7: "1.75rem", // 28px 8: "2rem", // 32px 9: "2.25rem", // 36px 10: "2.5rem", // 40px 12: "3rem", // 48px 14: "3.5rem", // 56px 16: "4rem", // 64px 20: "5rem", // 80px 24: "6rem", // 96px 32: "8rem", // 128px }, radius: { none: "0", xs: "0.25rem", // 4px sm: "0.375rem", // 6px md: "0.5rem", // 8px lg: "0.75rem", // 12px xl: "1rem", // 16px "2xl": "1.5rem", // 24px "3xl": "2rem", // 32px round: "9999px", circle: "50%", }, shadow: { xs: "0 1px 2px 0 rgba(0, 0, 0, 0.05)", sm: "0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px -1px rgba(0, 0, 0, 0.1)", md: "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1)", lg: "0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1)", xl: "0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1)", "2xl": "0 25px 50px -12px rgba(0, 0, 0, 0.25)", inner: "inset 0 2px 4px 0 rgba(0, 0, 0, 0.05)", glow: "0 0 20px rgba(253, 11, 110, 0.3), 0 0 40px rgba(253, 11, 110, 0.15)", glowStrong: "0 0 30px rgba(253, 11, 110, 0.5), 0 0 60px rgba(253, 11, 110, 0.3)", shadowCardHover: "0 20px 55px rgba(6, 6, 8, 0.55)", shadowElevated: "0 24px 60px rgba(0, 0, 0, 0.45)", }, motion: { easing: { standard: "cubic-bezier(0.2, 0.8, 0.2, 1)", emphasized: "cubic-bezier(0.4, 0, 0.2, 1)", decelerate: "cubic-bezier(0, 0, 0.2, 1)", accelerate: "cubic-bezier(0.4, 0, 1, 1)", sharp: "cubic-bezier(0.4, 0, 0.6, 1)", }, duration: { instant: "50ms", fast: "120ms", base: "200ms", slow: "300ms", slower: "400ms", }, }, layout: { container: { xs: "20rem", // 320px sm: "24rem", // 384px md: "28rem", // 448px lg: "32rem", // 512px xl: "36rem", // 576px "2xl": "42rem", // 672px }, measure: "65ch", }, borderWidth: { thin: "1px", base: "2px", thick: "4px", }, zIndex: { bg: 0, base: 1, content: 10, dropdown: 100, sticky: 200, overlay: 500, modal: 1000, popover: 1100, tooltip: 1200, toast: 1300, }, }; /** * Dark theme token overrides */ export const darkThemeTokens: Partial = { color: { brand: { ...designTokens.color.brand, }, semantic: { background: "hsl(0 0% 0%)", foreground: "hsl(0 0% 100%)", surface: "hsl(0 0% 6%)", elev1: "hsl(0 0% 9%)", elev2: "hsl(0 0% 12%)", text: "hsl(0 0% 100%)", textMuted: "hsl(0 0% 60%)", textSubtle: "hsl(0 0% 42%)", border: "hsl(0 0% 20%)", borderSubtle: "hsl(0 0% 14%)", overlay: "hsla(0 0% 0% / 0.75)", // Add the new opacity-based surface tokens for dark theme surfaceOverlay: "rgba(7, 7, 8, 0.85)", overlayDark: "rgba(0, 0, 0, 0.5)", textPrimary: "rgba(255, 255, 255, 0.95)", textMutedLight: "rgba(255, 255, 255, 0.65)", textSubtleLight: "rgba(255, 255, 255, 0.8)", progressTrack: "rgba(255, 255, 255, 0.3)", // Dark workspace background (same for both themes) workspaceDark: "#060606", // New scrollbar tokens scrollbarThumb: "hsl(0 0% 40%)", scrollbarThumbHover: "hsl(0 0% 53%)", // New card token cardDark: "hsl(0 0% 6%)", }, ui: { card: "hsl(0 0% 6%)", cardForeground: "hsl(0 0% 100%)", popover: "hsl(0 0% 8%)", popoverForeground: "hsl(0 0% 100%)", primary: "hsl(0 0% 100%)", primaryForeground: "hsl(0 0% 100%)", secondary: "hsl(0 0% 20%)", secondaryForeground: "hsl(0 0% 95%)", muted: "hsl(0 0% 32%)", mutedForeground: "hsl(0 0% 75%)", accent: "hsl(243 100% 69%)", accentForeground: "hsl(0 0% 100%)", destructive: "hsl(0 84% 56%)", destructiveForeground: "hsl(0 0% 100%)", success: "hsl(87 100% 68%)", successForeground: "hsl(0 0% 12%)", warning: "hsl(45 100% 52%)", warningForeground: "hsl(0 0% 8%)", info: "hsl(243 100% 69%)", infoForeground: "hsl(0 0% 100%)", input: "hsl(0 0% 20%)", ring: "hsl(0 0% 100%)", }, gray: { ...designTokens.color.gray, }, chart: { ...designTokens.color.chart, }, }, }; /** * Export individual token groups for tree-shaking */ export const colors = designTokens.color; export const typography = designTokens.typography; export const spacing = designTokens.spacing; export const radius = designTokens.radius; export const shadow = designTokens.shadow; export const motion = designTokens.motion; export const layout = designTokens.layout; export const borderWidth = designTokens.borderWidth; export const zIndex = designTokens.zIndex;