Skip to Content
Veltix
ThemesColor Palettes

Color Palettes

Veltix provides comprehensive color palette management with predefined palettes and custom color generation tools.

Overview

Color palette features include:

  • Predefined Palettes: Ready-to-use color schemes
  • Custom Palettes: Create brand-specific color schemes
  • Accessibility Tools: WCAG compliant color combinations
  • Color Generation: Automated palette creation
  • Palette Management: Import, export, and organize palettes

Predefined Palettes

Default Palettes

// Veltix default color palettes const defaultPalettes = { blue: { name: 'Blue', colors: { 50: '#eff6ff', 100: '#dbeafe', 200: '#bfdbfe', 300: '#93c5fd', 400: '#60a5fa', 500: '#3b82f6', 600: '#2563eb', 700: '#1d4ed8', 800: '#1e40af', 900: '#1e3a8a' } }, green: { name: 'Green', colors: { 50: '#f0fdf4', 100: '#dcfce7', 200: '#bbf7d0', 300: '#86efac', 400: '#4ade80', 500: '#22c55e', 600: '#16a34a', 700: '#15803d', 800: '#166534', 900: '#14532d' } }, purple: { name: 'Purple', colors: { 50: '#faf5ff', 100: '#f3e8ff', 200: '#e9d5ff', 300: '#d8b4fe', 400: '#c084fc', 500: '#a855f7', 600: '#9333ea', 700: '#7c3aed', 800: '#6b21a8', 900: '#581c87' } }, red: { name: 'Red', colors: { 50: '#fef2f2', 100: '#fee2e2', 200: '#fecaca', 300: '#fca5a5', 400: '#f87171', 500: '#ef4444', 600: '#dc2626', 700: '#b91c1c', 800: '#991b1b', 900: '#7f1d1d' } }, orange: { name: 'Orange', colors: { 50: '#fff7ed', 100: '#ffedd5', 200: '#fed7aa', 300: '#fdba74', 400: '#fb923c', 500: '#f97316', 600: '#ea580c', 700: '#c2410c', 800: '#9a3412', 900: '#7c2d12' } } };

Semantic Palettes

// Semantic color palettes for different contexts const semanticPalettes = { success: { name: 'Success', colors: { 50: '#f0fdf4', 100: '#dcfce7', 200: '#bbf7d0', 300: '#86efac', 400: '#4ade80', 500: '#22c55e', 600: '#16a34a', 700: '#15803d', 800: '#166534', 900: '#14532d' } }, warning: { name: 'Warning', colors: { 50: '#fffbeb', 100: '#fef3c7', 200: '#fde68a', 300: '#fcd34d', 400: '#fbbf24', 500: '#f59e0b', 600: '#d97706', 700: '#b45309', 800: '#92400e', 900: '#78350f' } }, error: { name: 'Error', colors: { 50: '#fef2f2', 100: '#fee2e2', 200: '#fecaca', 300: '#fca5a5', 400: '#f87171', 500: '#ef4444', 600: '#dc2626', 700: '#b91c1c', 800: '#991b1b', 900: '#7f1d1d' } }, info: { name: 'Info', colors: { 50: '#eff6ff', 100: '#dbeafe', 200: '#bfdbfe', 300: '#93c5fd', 400: '#60a5fa', 500: '#3b82f6', 600: '#2563eb', 700: '#1d4ed8', 800: '#1e40af', 900: '#1e3a8a' } } };

Custom Palette Creation

Manual Palette Creation

// Create custom palette manually const createCustomPalette = (name, baseColor) => { return { name, colors: generateColorScale(baseColor), metadata: { createdAt: new Date().toISOString(), baseColor, type: 'custom' } }; }; // Color scale generation const generateColorScale = (baseColor) => { const colors = {}; const steps = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900]; steps.forEach(step => { const lightness = step === 500 ? 50 : step < 500 ? 50 + (500 - step) * 0.1 : step > 500 ? 50 - (step - 500) * 0.1 : 50; colors[step] = adjustColorLightness(baseColor, lightness); }); return colors; }; // Color adjustment utility const adjustColorLightness = (color, lightness) => { // Convert hex to HSL, adjust lightness, convert back to hex const hsl = hexToHsl(color); hsl.l = Math.max(0, Math.min(100, lightness)); return hslToHex(hsl); };

Palette from Image

// Extract palette from image const extractPaletteFromImage = async (imageUrl) => { return new Promise((resolve, reject) => { const img = new Image(); img.crossOrigin = 'anonymous'; img.onload = () => { const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); canvas.width = img.width; canvas.height = img.height; ctx.drawImage(img, 0, 0); const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); const colors = extractColorsFromImageData(imageData); resolve({ name: 'Extracted Palette', colors: generatePaletteFromColors(colors), metadata: { source: imageUrl, extractedAt: new Date().toISOString() } }); }; img.onerror = reject; img.src = imageUrl; }); }; // Extract dominant colors from image data const extractColorsFromImageData = (imageData) => { const colors = new Map(); const data = imageData.data; for (let i = 0; i < data.length; i += 4) { const r = data[i]; const g = data[i + 1]; const b = data[i + 2]; const hex = rgbToHex(r, g, b); colors.set(hex, (colors.get(hex) || 0) + 1); } // Sort by frequency and return top colors return Array.from(colors.entries()) .sort((a, b) => b[1] - a[1]) .slice(0, 5) .map(([color]) => color); };

Palette Management

Palette Registry

// Palette registry for management class PaletteRegistry { constructor() { this.palettes = new Map(); this.activePalette = null; } register(name, palette) { this.palettes.set(name, palette); return true; } get(name) { return this.palettes.get(name); } list() { return Array.from(this.palettes.keys()); } remove(name) { return this.palettes.delete(name); } setActive(name) { if (!this.palettes.has(name)) { throw new Error(`Palette ${name} not found`); } this.activePalette = name; return this.palettes.get(name); } getActive() { return this.activePalette ? this.palettes.get(this.activePalette) : null; } export(name) { const palette = this.get(name); if (!palette) return null; return JSON.stringify(palette, null, 2); } import(paletteData) { try { const palette = JSON.parse(paletteData); if (!palette.name || !palette.colors) { throw new Error('Invalid palette format'); } this.register(palette.name, palette); return { success: true, palette: palette.name }; } catch (error) { return { success: false, error: error.message }; } } } // Global palette registry const paletteRegistry = new PaletteRegistry();

Palette Utilities

// Palette utility functions const paletteUtils = { // Get color from palette getColor: (palette, shade = 500) => { return palette.colors[shade]; }, // Get contrasting text color getContrastColor: (backgroundColor) => { const brightness = getColorBrightness(backgroundColor); return brightness > 128 ? '#000000' : '#ffffff'; }, // Check color accessibility checkAccessibility: (foreground, background) => { const ratio = calculateContrastRatio(foreground, background); return { ratio, isAACompliant: ratio >= 4.5, isAAACompliant: ratio >= 7, level: ratio >= 7 ? 'AAA' : ratio >= 4.5 ? 'AA' : 'Fail' }; }, // Generate complementary colors getComplementary: (color) => { const hsl = hexToHsl(color); hsl.h = (hsl.h + 180) % 360; return hslToHex(hsl); }, // Generate analogous colors getAnalogous: (color, count = 3) => { const hsl = hexToHsl(color); const colors = []; for (let i = 0; i < count; i++) { const hue = (hsl.h + (i - Math.floor(count / 2)) * 30) % 360; colors.push(hslToHex({ ...hsl, h: hue })); } return colors; } }; // Color conversion utilities const colorUtils = { hexToHsl: (hex) => { // Convert hex to HSL const r = parseInt(hex.slice(1, 3), 16) / 255; const g = parseInt(hex.slice(3, 5), 16) / 255; const b = parseInt(hex.slice(5, 7), 16) / 255; const max = Math.max(r, g, b); const min = Math.min(r, g, b); let h, s, l = (max + min) / 2; if (max === min) { h = s = 0; } else { const d = max - min; s = l > 0.5 ? d / (2 - max - min) : d / (max + min); switch (max) { case r: h = (g - b) / d + (g < b ? 6 : 0); break; case g: h = (b - r) / d + 2; break; case b: h = (r - g) / d + 4; break; } h /= 6; } return { h: h * 360, s: s * 100, l: l * 100 }; }, hslToHex: (hsl) => { // Convert HSL to hex const h = hsl.h / 360; const s = hsl.s / 100; const l = hsl.l / 100; const hue2rgb = (p, q, t) => { 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; }; let r, g, b; if (s === 0) { r = g = b = l; } else { const q = l < 0.5 ? l * (1 + s) : l + s - l * s; const p = 2 * l - q; r = hue2rgb(p, q, h + 1/3); g = hue2rgb(p, q, h); b = hue2rgb(p, q, h - 1/3); } const toHex = (c) => { const hex = Math.round(c * 255).toString(16); return hex.length === 1 ? '0' + hex : hex; }; return `#${toHex(r)}${toHex(g)}${toHex(b)}`; } };

Accessibility Tools

Contrast Checking

// Contrast ratio calculation const calculateContrastRatio = (color1, color2) => { const luminance1 = getColorLuminance(color1); const luminance2 = getColorLuminance(color2); const lighter = Math.max(luminance1, luminance2); const darker = Math.min(luminance1, luminance2); return (lighter + 0.05) / (darker + 0.05); }; // Color luminance calculation const getColorLuminance = (color) => { const rgb = hexToRgb(color); const [r, g, b] = [rgb.r, rgb.g, rgb.b].map(c => { c = c / 255; return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4); }); return 0.2126 * r + 0.7152 * g + 0.0722 * b; }; // Accessibility checker component function AccessibilityChecker({ foreground, background }) { const contrast = calculateContrastRatio(foreground, background); const isAACompliant = contrast >= 4.5; const isAAACompliant = contrast >= 7; return ( <div className="accessibility-checker"> <div className="color-preview" style={{ backgroundColor: background, color: foreground }}> Sample Text </div> <div className="contrast-info"> <p>Contrast Ratio: {contrast.toFixed(2)}:1</p> <p>WCAG AA: {isAACompliant ? '✅ Pass' : '❌ Fail'}</p> <p>WCAG AAA: {isAAACompliant ? '✅ Pass' : '❌ Fail'}</p> </div> </div> ); }

Color Blindness Simulation

// Color blindness simulation const colorBlindnessTypes = { protanopia: { name: 'Protanopia (Red-Blind)', matrix: [ [0.567, 0.433, 0], [0.558, 0.442, 0], [0, 0.242, 0.758] ] }, deuteranopia: { name: 'Deuteranopia (Green-Blind)', matrix: [ [0.625, 0.375, 0], [0.7, 0.3, 0], [0, 0.3, 0.7] ] }, tritanopia: { name: 'Tritanopia (Blue-Blind)', matrix: [ [0.95, 0.05, 0], [0, 0.433, 0.567], [0, 0.475, 0.525] ] } }; // Simulate color blindness const simulateColorBlindness = (color, type) => { const rgb = hexToRgb(color); const matrix = colorBlindnessTypes[type].matrix; const newR = Math.round( matrix[0][0] * rgb.r + matrix[0][1] * rgb.g + matrix[0][2] * rgb.b ); const newG = Math.round( matrix[1][0] * rgb.r + matrix[1][1] * rgb.g + matrix[1][2] * rgb.b ); const newB = Math.round( matrix[2][0] * rgb.r + matrix[2][1] * rgb.g + matrix[2][2] * rgb.b ); return rgbToHex(newR, newG, newB); }; // Color blindness simulator component function ColorBlindnessSimulator({ palette }) { const [simulationType, setSimulationType] = useState('normal'); const simulatedColors = useMemo(() => { if (simulationType === 'normal') return palette.colors; const simulated = {}; Object.entries(palette.colors).forEach(([shade, color]) => { simulated[shade] = simulateColorBlindness(color, simulationType); }); return simulated; }, [palette, simulationType]); return ( <div className="color-blindness-simulator"> <select value={simulationType} onChange={(e) => setSimulationType(e.target.value)}> <option value="normal">Normal Vision</option> <option value="protanopia">Protanopia</option> <option value="deuteranopia">Deuteranopia</option> <option value="tritanopia">Tritanopia</option> </select> <div className="color-swatch"> {Object.entries(simulatedColors).map(([shade, color]) => ( <div key={shade} className="color-sample" style={{ backgroundColor: color }} title={`${shade}: ${color}`} /> ))} </div> </div> ); }

Palette Export and Import

Export Formats

// Export palette in different formats const exportPalette = (palette, format = 'json') => { switch (format) { case 'json': return JSON.stringify(palette, null, 2); case 'css': return generateCSSVariables(palette); case 'scss': return generateSCSSVariables(palette); case 'tailwind': return generateTailwindConfig(palette); default: throw new Error(`Unsupported format: ${format}`); } }; // Generate CSS variables const generateCSSVariables = (palette) => { let css = `/* ${palette.name} Color Palette */\n:root {\n`; Object.entries(palette.colors).forEach(([shade, color]) => { css += ` --color-${palette.name.toLowerCase()}-${shade}: ${color};\n`; }); css += '}'; return css; }; // Generate Tailwind config const generateTailwindConfig = (palette) => { const colors = {}; Object.entries(palette.colors).forEach(([shade, color]) => { colors[shade] = color; }); return `module.exports = { theme: { extend: { colors: { '${palette.name.toLowerCase()}': ${JSON.stringify(colors, null, 2)} } } } }`; };

Import from Various Sources

// Import palette from different sources const importPalette = async (source, type) => { switch (type) { case 'json': return importFromJSON(source); case 'image': return await extractPaletteFromImage(source); case 'url': return await importFromURL(source); case 'adobe': return importFromAdobe(source); default: throw new Error(`Unsupported import type: ${type}`); } }; // Import from Adobe Color const importFromAdobe = (adobeUrl) => { // Parse Adobe Color URL and extract colors const colors = extractColorsFromAdobeURL(adobeUrl); return { name: 'Adobe Color Palette', colors: generateColorScale(colors[0]), metadata: { source: 'Adobe Color', url: adobeUrl, importedAt: new Date().toISOString() } }; };

Best Practices

1. Color Selection

  • Use semantic color names
  • Maintain consistent color scales
  • Consider cultural color meanings
  • Test colors in different contexts

2. Accessibility

  • Ensure sufficient contrast ratios
  • Test with color blindness simulators
  • Provide alternative color schemes
  • Follow WCAG guidelines

3. Organization

  • Use descriptive palette names
  • Version your palettes
  • Document color purposes
  • Organize by project or brand

4. Performance

  • Cache color calculations
  • Optimize color generation
  • Use efficient color formats
  • Minimize palette complexity

Troubleshooting

Common Issues

Colors not displaying correctly

  • Check color format validity
  • Verify color space conversion
  • Test in different browsers
  • Validate color values

Accessibility issues

  • Check contrast ratios
  • Test with color blindness tools
  • Provide alternative colors
  • Follow accessibility guidelines

Performance problems

  • Optimize color generation
  • Cache color calculations
  • Use efficient color formats
  • Monitor memory usage
Last updated on