惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
美团技术团队
Last Week in AI
Last Week in AI
WordPress大学
WordPress大学
博客园 - 三生石上(FineUI控件)
博客园 - 聂微东
雷峰网
雷峰网
阮一峰的网络日志
阮一峰的网络日志
博客园 - 叶小钗
IT之家
IT之家
Google DeepMind News
Google DeepMind News
D
Docker
J
Java Code Geeks
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Apple Machine Learning Research
Apple Machine Learning Research
博客园 - 【当耐特】
V
V2EX
Hugging Face - Blog
Hugging Face - Blog
博客园 - Franky
月光博客
月光博客
宝玉的分享
宝玉的分享
酷 壳 – CoolShell
酷 壳 – CoolShell
aimingoo的专栏
aimingoo的专栏
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
color-zone — A React Color Picker with Gradient Support, ...
Naxrul Ahmed · 2026-06-23 · via DEV Community

Naxrul Ahmed


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


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} />;
}

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} />

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>
  );
}


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 }


Hiding what you don't need

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


TypeScript

import type {
  ColorPickerProps,
  UseColorPickerReturn,
  GradientStop,
  ParsedGradient,
} from "color-zone";


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.