DEV Community

Naxrul Ahmed
Naxrul Ahmed

Posted on

color-zone — A React Color Picker with Gradient Support, EyeDropper, and a Headless Hook


title: "color-zone — A React Color Picker with Gradient Support, EyeDropper, and a Headless Hook"
published: true
tags: react, typescript, opensource, webdev

description: "A zero-dependency React color picker supporting HSV, RGB, HSL, HEX, linear/radial gradients, EyeDropper API, and a headless useColorPicker hook."

I built a React color picker that actually handles gradients

Most color picker libraries handle solid colors well. As soon as you need gradient support — letting users build linear-gradient or radial-gradient values with multiple stops — you're either stitching together multiple libraries or building it yourself.

I needed exactly that for a project, so I built color-zone.


What it does

  • HSV picker square with hue and alpha sliders
  • Switchable input modes: HEX, RGB, HSL
  • Full gradient editing — linear and radial, with draggable multi-stop bar
  • EyeDropper API for sampling any color on screen
  • A useColorPicker hook for headless / custom UIs
  • Zero runtime dependencies
  • Full TypeScript support

Install

npm install color-zone
Enter fullscreen mode Exit fullscreen mode

Basic usage

import { ColorPicker } from "color-zone";
import { useState } from "react";

export default function App() {
  const [color, setColor] = useState("#3498db");

  return <ColorPicker value={color} onChange={setColor} />;
}
Enter fullscreen mode Exit fullscreen mode

That's it. The picker is a controlled component — you own the state, it calls onChange on every update.


Gradient mode is automatic

Pass a CSS gradient string and the picker switches into gradient mode — no extra config needed.

const [bg, setBg] = useState(
  "linear-gradient(90deg, #e52d27 0%, #b31217 100%)"
);

<ColorPicker value={bg} onChange={setBg} />
Enter fullscreen mode Exit fullscreen mode

Users get a full stop bar: click to add a stop, drag to reposition, double-click to remove. The onChange callback returns a valid CSS gradient string you can apply directly to background.


The headless hook

If you want full control over the UI, skip the component and use useColorPicker instead.

import { useColorPicker } from "color-zone";

function CustomPicker() {
  const [color, setColor] = useState("#e74c3c");
  const {
    valueToHex,
    valueToHSL,
    valueToCmyk,
    setR, setG, setB, setA,
    setHue, setSaturation, setLightness,
    setLinear, setRadial, setDegrees,
    addPoint, deletePoint, setSelectedPoint,
  } = useColorPicker(color, setColor);

  return (
    <div>
      <p>HEX: {valueToHex()}</p>
      <p>HSL: {valueToHSL()}</p>
      <p>CMYK: {valueToCmyk()}</p>
      <button onClick={() => setLinear()}>Make Linear Gradient</button>
      <button onClick={() => setRadial()}>Make Radial Gradient</button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Color utilities are exported too

import {
  rgb2hsl, rgb2hsv, rgb2cmyk,
  hsv2rgb, toHex, toHexA,
  parseColor, parseGradient, buildGradientString,
} from "color-zone";

const [h, s, l] = rgb2hsl(255, 99, 71);
// → [9, 100, 64]

const parsed = parseColor("rgba(255, 99, 71, 0.8)");
// → { r: 255, g: 99, b: 71, a: 0.8 }
Enter fullscreen mode Exit fullscreen mode

Hiding what you don't need

// Minimal — hue + alpha sliders only
<ColorPicker
  value={color}
  onChange={setColor}
  hidePickerSquare
  hideInputs
  hideEyeDrop
/>
Enter fullscreen mode Exit fullscreen mode

TypeScript

import type {
  ColorPickerProps,
  UseColorPickerReturn,
  GradientStop,
  ParsedGradient,
} from "color-zone";
Enter fullscreen mode Exit fullscreen mode

EyeDropper

On Chrome/Edge 95+, a dropper button appears automatically — no configuration needed. Silently hidden everywhere else.


Links


Let me know if you run into issues or have feature requests — happy to take them in the issues tab.

Top comments (0)