ColorAssembly
Use cases

Design System Generator

Generate complete design system color palettes with ColorAssembly

Build a professional design system generator that creates cohesive, accessible color palettes for your entire product.

What You'll Build

A tool that generates:

  • Primary color scales (50-900)
  • Semantic colors (success, warning, error, info)
  • Neutral/gray scales
  • Dark mode variants
  • CSS/Tailwind export

Complete Implementation

'use client';
 
import { useState, useEffect } from 'react';
import { loadColorAssembly, type ColorAssemblyAPI, type RGB } from '@cymbol/colorassembly';
 
export function DesignSystemGenerator() {
  const [api, setApi] = useState<ColorAssemblyAPI | null>(null);
  const [brandColor, setBrandColor] = useState('#6366f1');
  
  useEffect(() => {
    loadColorAssembly().then(setApi);
  }, []);
 
  if (!api) return <div>Loading...</div>;
 
  const rgb = api.transforms.hexToRgb({ hex: brandColor });
  const primaryScale = api.generate.primaryScale(rgb);
  const neutralScale = api.generate.neutralScale(rgb);
  const semanticPalette = api.generate.semanticPalette(rgb, 'light');
 
  const exportAsCSS = () => {
    let css = ':root {\n';
    
    // Primary scale
    primaryScale.forEach((color, i) => {
      const hex = api.transforms.rgbToHex(color);
      css += `  --color-primary-${(i + 1) * 100}: ${hex.hex};\n`;
    });
    
    // Neutrals
    neutralScale.forEach((color, i) => {
      const hex = api.transforms.rgbToHex(color);
      css += `  --color-gray-${(i + 1) * 100}: ${hex.hex};\n`;
    });
    
    // Semantic
    Object.entries(semanticPalette).forEach(([name, rgb]) => {
      const hex = api.transforms.rgbToHex(rgb as RGB);
      css += `  --color-${name.toLowerCase()}: ${hex.hex};\n`;
    });
    
    css += '}';
    
    navigator.clipboard.writeText(css);
    alert('CSS variables copied!');
  };
 
  const exportAsTailwind = () => {
    const config = {
      colors: {
        primary: Object.fromEntries(
          primaryScale.map((color, i) => {
            const hex = api.transforms.rgbToHex(color);
            return [(i + 1) * 100, hex.hex];
          })
        ),
        gray: Object.fromEntries(
          neutralScale.map((color, i) => {
            const hex = api.transforms.rgbToHex(color);
            return [(i + 1) * 100, hex.hex];
          })
        ),
        semantic: Object.fromEntries(
          Object.entries(semanticPalette).map(([name, rgb]) => {
            const hex = api.transforms.rgbToHex(rgb as RGB);
            return [name, hex.hex];
          })
        ),
      },
    };
    
    navigator.clipboard.writeText(JSON.stringify(config, null, 2));
    alert('Tailwind config copied!');
  };
 
  return (
    <div className="max-w-6xl mx-auto p-8 space-y-12">
      {/* Header */}
      <div>
        <h1 className="text-4xl font-bold mb-2">Design System Generator</h1>
        <p className="text-gray-600">
          Generate a complete, accessible color system from your brand color
        </p>
      </div>
 
      {/* Brand Color Input */}
      <div className="p-6 border rounded-lg">
        <label className="block text-lg font-semibold mb-4">Brand Color</label>
        <div className="flex gap-4">
          <input
            type="color"
            value={brandColor}
            onChange={(e) => setBrandColor(e.target.value)}
            className="w-24 h-24 rounded-lg cursor-pointer"
          />
          <div className="flex-1">
            <input
              type="text"
              value={brandColor}
              onChange={(e) => setBrandColor(e.target.value)}
              className="w-full px-4 py-2 border rounded-lg font-mono"
              placeholder="#6366f1"
            />
            <p className="text-sm text-gray-600 mt-2">
              This will be your primary-500 color
            </p>
          </div>
        </div>
      </div>
 
      {/* Primary Scale */}
      <section>
        <h2 className="text-2xl font-bold mb-4">Primary Colors</h2>
        <div className="grid grid-cols-10 gap-2">
          {primaryScale.map((color, i) => {
            const hex = api.transforms.rgbToHex(color);
            const textColor = api.analyze.suggestTextColor(color);
            const textHex = api.transforms.rgbToHex(textColor);
            const step = (i + 1) * 100;
            
            return (
              <div key={i} className="space-y-2">
                <div
                  className="h-24 rounded-lg flex items-center justify-center cursor-pointer hover:scale-105 transition shadow"
                  style={{ backgroundColor: hex.hex, color: textHex.hex }}
                  onClick={() => navigator.clipboard.writeText(hex.hex)}
                  title={`Click to copy ${hex.hex}`}
                >
                  <span className="font-bold text-sm">{step}</span>
                </div>
                <div className="text-xs text-center font-mono">{hex.hex}</div>
              </div>
            );
          })}
        </div>
      </section>
 
      {/* Neutral Scale */}
      <section>
        <h2 className="text-2xl font-bold mb-4">Neutral Colors</h2>
        <p className="text-sm text-gray-600 mb-4">
          Grays tinted with your brand color for visual harmony
        </p>
        <div className="grid grid-cols-10 gap-2">
          {neutralScale.map((color, i) => {
            const hex = api.transforms.rgbToHex(color);
            const textColor = api.analyze.suggestTextColor(color);
            const textHex = api.transforms.rgbToHex(textColor);
            const step = (i + 1) * 100;
            
            return (
              <div key={i} className="space-y-2">
                <div
                  className="h-24 rounded-lg flex items-center justify-center cursor-pointer hover:scale-105 transition shadow"
                  style={{ backgroundColor: hex.hex, color: textHex.hex }}
                  onClick={() => navigator.clipboard.writeText(hex.hex)}
                >
                  <span className="font-bold text-sm">{step}</span>
                </div>
                <div className="text-xs text-center font-mono">{hex.hex}</div>
              </div>
            );
          })}
        </div>
      </section>
 
      {/* Semantic Colors */}
      <section>
        <h2 className="text-2xl font-bold mb-4">Semantic Colors</h2>
        <div className="grid md:grid-cols-2 lg:grid-cols-4 gap-4">
          {['success', 'warning', 'error', 'info'].map((name) => {
            const color = semanticPalette[name as keyof typeof semanticPalette] as RGB;
            const hex = api.transforms.rgbToHex(color);
            const textColor = api.analyze.suggestTextColor(color);
            const textHex = api.transforms.rgbToHex(textColor);
            const onColor = semanticPalette[`on${name.charAt(0).toUpperCase() + name.slice(1)}` as keyof typeof semanticPalette] as RGB;
            const onHex = api.transforms.rgbToHex(onColor);
            
            return (
              <div key={name} className="border rounded-lg overflow-hidden">
                <div
                  className="h-32 flex items-center justify-center cursor-pointer"
                  style={{ backgroundColor: hex.hex, color: onHex.hex }}
                  onClick={() => navigator.clipboard.writeText(hex.hex)}
                >
                  <div className="text-center">
                    <div className="text-2xl font-bold capitalize">{name}</div>
                    <div className="text-sm font-mono mt-1">{hex.hex}</div>
                  </div>
                </div>
                <div className="p-3 bg-gray-50">
                  <div className="text-xs text-gray-600">Text color: {onHex.hex}</div>
                </div>
              </div>
            );
          })}
        </div>
      </section>
 
      {/* Preview */}
      <section>
        <h2 className="text-2xl font-bold mb-4">UI Preview</h2>
        <div className="border rounded-lg p-8 space-y-4" style={{ 
          backgroundColor: api.transforms.rgbToHex(semanticPalette.background).hex,
          color: api.transforms.rgbToHex(semanticPalette.text).hex 
        }}>
          <h3 className="text-2xl font-bold">Sample Interface</h3>
          <p style={{ color: api.transforms.rgbToHex(semanticPalette.textMuted).hex }}>
            This is how your design system looks in action
          </p>
          
          <div className="flex gap-2">
            <button
              className="px-4 py-2 rounded font-semibold"
              style={{
                backgroundColor: api.transforms.rgbToHex(semanticPalette.primary).hex,
                color: api.transforms.rgbToHex(semanticPalette.onPrimary).hex,
              }}
            >
              Primary Button
            </button>
            <button
              className="px-4 py-2 rounded font-semibold"
              style={{
                backgroundColor: api.transforms.rgbToHex(semanticPalette.success).hex,
                color: api.transforms.rgbToHex(semanticPalette.onSuccess).hex,
              }}
            >
              Success
            </button>
            <button
              className="px-4 py-2 rounded font-semibold"
              style={{
                backgroundColor: api.transforms.rgbToHex(semanticPalette.error).hex,
                color: api.transforms.rgbToHex(semanticPalette.onError).hex,
              }}
            >
              Error
            </button>
          </div>
        </div>
      </section>
 
      {/* Export */}
      <section className="flex gap-4">
        <button
          onClick={exportAsCSS}
          className="flex-1 px-6 py-4 bg-blue-600 text-white rounded-lg font-semibold hover:bg-blue-700 transition"
        >
          Export as CSS Variables
        </button>
        <button
          onClick={exportAsTailwind}
          className="flex-1 px-6 py-4 bg-cyan-600 text-white rounded-lg font-semibold hover:bg-cyan-700 transition"
        >
          Export as Tailwind Config
        </button>
      </section>
    </div>
  );
}

Example Exports

CSS Variables

:root {
  /* Primary Scale */
  --color-primary-100: #e0e7ff;
  --color-primary-200: #c7d2fe;
  --color-primary-300: #a5b4fc;
  --color-primary-400: #818cf8;
  --color-primary-500: #6366f1;
  --color-primary-600: #4f46e5;
  --color-primary-700: #4338ca;
  --color-primary-800: #3730a3;
  --color-primary-900: #312e81;
 
  /* Semantic */
  --color-success: #10b981;
  --color-warning: #f59e0b;
  --color-error: #ef4444;
  --color-info: #3b82f6;
}

Tailwind Config

module.exports = {
  theme: {
    extend: {
      colors: {
        primary: {
          100: '#e0e7ff',
          200: '#c7d2fe',
          300: '#a5b4fc',
          400: '#818cf8',
          500: '#6366f1',
          600: '#4f46e5',
          700: '#4338ca',
          800: '#3730a3',
          900: '#312e81',
        },
        // ... more colors
      },
    },
  },
};

Next Steps

On this page