Color Picker

intermediate
35 min

Explorer

1
⚛️
ColorPicker.jsx

Click files to view code →

React Color Picker Component Tutorial

1. What is the Question and What to Achieve Here

Create an interactive color picker component that allows users to select colors using different methods (RGB sliders, hex input, preset colors). The component should display the selected color and provide the color value in different formats.

[!TIP] Goal

  • Allow color selection through RGB sliders
  • Support hex color input
  • Display color preview
  • Show color values in multiple formats (RGB, HEX)
  • Provide preset color swatches
  • Make the component reusable with callbacks

2. How to Solve

Use React's

text
useState
hook to manage RGB values (red, green, blue). Convert between RGB and hex formats as needed. Use range input sliders for RGB control and provide a text input for direct hex entry.

3. What Are the Things That Need to Be Gathered

[!IMPORTANT] Requirements

  • React with hooks
  • Understanding of:
    • RGB color model (0-255 for each channel)
    • Hex color format (#RRGGBB)
    • Color conversion algorithms
    • Range input elements
    • Controlled components

No external dependencies needed.

4. Key Topics to Consider and Plan of Action

Key Topics:

  • Color Representation: RGB vs Hex formats
  • Color Conversion: Converting between RGB and hex
  • State Synchronization: Keeping sliders and hex input in sync
  • Input Validation: Validating hex color codes
  • Visual Preview: Displaying the selected color
  • Callback Pattern: Notifying parent of color changes

Plan of Action:

  1. Create
    text
    ColorPicker
    component
  2. Initialize state for RGB values (r, g, b)
  3. Create RGB to hex conversion function
  4. Create hex to RGB conversion function
  5. Build RGB slider controls
  6. Add hex input field
  7. Create color preview display
  8. Add preset color swatches
  9. Implement onChange callback

5. Code the Question

jsxShowing 50 of 174 lines
import React, { useState, useEffect } from 'react';
import './ColorPicker.css';

function ColorPicker({ 
  initialColor = '#3498db',
  onChange
}) {
  // Parse initial color to RGB
  const parseHex = (hex) => {
    const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
    return result ? {
      r: parseInt(result[1], 16),
      g: parseInt(result[2], 16),
      b: parseInt(result[3], 16)
    } : { r: 52, g: 152, b: 219 };
  };

  const initial = parseHex(initialColor);
  const [red, setRed] = useState(initial.r);
  const [green, setGreen] = useState(initial.g);
  const [blue, setBlue] = useState(initial.b);

  // Convert RGB to Hex
  const rgbToHex = (r, g, b) => {
    const toHex = (n) => {
      const hex = n.toString(16);
      return hex.length === 1 ? '0' + hex : hex;
    };
    return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
  };

  const currentHex = rgbToHex(red, green, blue);
  const currentRgb = `rgb(${red}, ${green}, ${blue})`;

  // Preset colors
  const presetColors = [
    '#e74c3c', '#3498db', '#2ecc71', '#f39c12', 
    '#9b59b6', '#1abc9c', '#34495e', '#95a5a6',
    '#e67e22', '#16a085', '#c0392b', '#8e44ad',
    '#2c3e50', '#d35400', '#27ae60', '#2980b9'
  ];

  // Notify parent of color changes
  useEffect(() => {
    if (onChange) {
      onChange(currentHex, currentRgb, { r: red, g: green, b: blue });
    }
  }, [red, green, blue]);

  // Handle hex input change
// ...

CSS Styling (ColorPicker.css):

cssShowing 50 of 184 lines
.color-picker {
  max-width: 400px;
  margin: 2rem auto;
  padding: 2rem;
  background: #fff;
  border-radius: 12px;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
  font-family: Arial, sans-serif;
}

.color-picker h2 {
  margin-top: 0;
  color: #333;
  text-align: center;
}

.color-preview {
  height: 150px;
  border-radius: 8px;
  margin: 1.5rem 0;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding: 1rem;
  box-shadow: inset 0 2px 8px rgba(0, 0, 0, 0.2);
  transition: background-color 0.2s ease;
}

.color-info {
  background: rgba(255, 255, 255, 0.95);
  padding: 0.75rem 1rem;
  border-radius: 6px;
  text-align: center;
}

.color-value {
  font-family: 'Courier New', monospace;
  font-size: 0.875rem;
  font-weight: 600;
  color: #333;
  margin: 0.25rem 0;
}

.sliders-container {
  margin: 1.5rem 0;
}

.slider-group {
  margin-bottom: 1.25rem;
}
// ...

Usage Example:

jsx
import React, { useState } from 'react';
import ColorPicker from './ColorPicker';

function App() {
  const [selectedColor, setSelectedColor] = useState('#3498db');

  const handleColorChange = (hex, rgb, rgbObj) => {
    setSelectedColor(hex);
    console.log('Selected:', { hex, rgb, rgbObj });
  };

  return (
    <div className="app">
      <ColorPicker
        initialColor="#3498db"
        onChange={handleColorChange}
      />
      
      <div style={{ 
        marginTop: '2rem', 
        padding: '2rem', 
        backgroundColor: selectedColor,
        color: 'white',
        textAlign: 'center'
      }}>
        <h2>Preview Area</h2>
        <p>Current color: {selectedColor}</p>
      </div>
    </div>
  );
}

6. Things to Consider

Best Practices:

  • Color Conversion: Ensure accurate RGB ↔ Hex conversions
  • Input Validation: Validate hex input format
  • Performance: Use debouncing for onChange callbacks if needed
  • Accessibility: Provide labels and ARIA attributes
  • Visual Feedback: Show current values clearly

Common Pitfalls:

  • Don't forget to pad single-digit hex values with zeros
  • Handle uppercase and lowercase hex inputs
  • Ensure hex input validates before updating RGB
  • Remember that RGB values are 0-255, not 0-100
  • Don't trigger onChange on every keystroke in hex input

Enhancements:

  • HSL/HSV Support: Add hue, saturation, lightness controls
  • Alpha Channel: Support transparency (RGBA, #RRGGBBAA)
  • Color Palette: Save favorite colors
  • Recent Colors: Show recently used colors
  • Color Harmony: Suggest complementary colors
  • Eyedropper: Sample colors from screen (if supported)
  • Named Colors: Support CSS color names
  • Gradient Picker: Create gradients

Advanced Version with Alpha:

jsx
function ColorPickerWithAlpha() {
  const [red, setRed] = useState(52);
  const [green, setGreen] = useState(152);
  const [blue, setBlue] = useState(219);
  const [alpha, setAlpha] = useState(1);

  const rgbaToHex = (r, g, b, a) => {
    const toHex = (n) => n.toString(16).padStart(2, '0');
    const alphaHex = Math.round(a * 255).toString(16).padStart(2, '0');
    return `#${toHex(r)}${toHex(g)}${toHex(b)}${alphaHex}`;
  };

  const currentRgba = `rgba(${red}, ${green}, ${blue}, ${alpha})`;

  return (
    <div className="color-picker">
      {/* Existing RGB sliders */}
      
      <div className="slider-group">
        <label>
          Opacity: <span>{Math.round(alpha * 100)}%</span>
        </label>
        <input
          type="range"
          min="0"
          max="1"
          step="0.01"
          value={alpha}
          onChange={(e) => setAlpha(parseFloat(e.target.value))}
          className="slider"
        />
      </div>

      <div style={{
        backgroundColor: currentRgba,
        backgroundImage: `
          linear-gradient(45deg, #ccc 25%, transparent 25%),
          linear-gradient(-45deg, #ccc 25%, transparent 25%),
          linear-gradient(45deg, transparent 75%, #ccc 75%),
          linear-gradient(-45deg, transparent 75%, #ccc 75%)
        `,
        backgroundSize: '20px 20px',
        backgroundPosition: '0 0, 0 10px, 10px -10px, -10px 0px'
      }}>
        Preview with transparency
      </div>
    </div>
  );
}

Testing Considerations:

  • Test RGB slider changes
  • Test hex input with valid/invalid values
  • Test preset color selection
  • Test edge values (0, 255, #000000, #ffffff)
  • Test color conversion accuracy
  • Test copy to clipboard functionality

Real-World Use Cases:

  • Theme customization
  • Design tools
  • Form builders
  • CSS editors
  • Drawing applications
  • Dashboard customization
  • Branding tools

This color picker component provides a complete color selection interface and can be extended with advanced features like gradients and color harmonies.

No files open

Click a file in the explorer to view