DEV Community

Sohail Khan
Sohail Khan

Posted on

How to Add a Production-Ready React Color Picker in 2026: Forms, Images, Eyedropper, Gradients & OKLCH

Adding a React color picker looks easy at first.

You install a component, pass it a color value, listen for changes, and you are done.

That works when all you need is a simple HEX color.

But real applications usually need more.

A settings page may need a color input that works with forms. A theme editor needs RGB and HSL controls. A design tool may need palettes, an eyedropper, gradients, or image color sampling. A modern design system may also need OKLCH and Display P3 instead of only HEX and RGB.

That is where a basic color input starts becoming a complete color workflow.

In this guide, I’ll show how to add a production-ready React color picker using ChromaPanel and gradually add the features that a real application may need.

ChromaPanel is an open-source React color picker with five picking modes, image sampling, an eyedropper, gradients, modern CSS color support, accessibility, native form behavior, TypeScript support, and zero runtime dependencies.

You can install it from npm and start with only a few lines of code.

Install the React color picker

Start by installing the package:

npm install chroma-panel
Enter fullscreen mode Exit fullscreen mode

Then import ColorInput.

import { ColorInput } from "chroma-panel";

export function BrandColor() {
  return <ColorInput defaultValue="#3366cc" />;
}
Enter fullscreen mode Exit fullscreen mode

That gives you a working React color input.

The user sees a color swatch. Clicking it opens the picker.

There is no provider to wrap around your application and no separate stylesheet required for the standard setup.

For a settings form or a simple customization page, this may already be enough.

Use a controlled React color picker

Most React applications eventually need the selected color somewhere else.

Maybe you want to update a preview, save a theme, change a button color, or store the value in your API.

In that case, use the normal controlled React pattern.

import { useState } from "react";
import { ColorInput } from "chroma-panel";

export function ThemeColor() {
  const [color, setColor] = useState("#7c3aed");

  return (
    <ColorInput
      value={color}
      onChange={(result) => setColor(result.hex)}
      aria-label="Theme color"
    />
  );
}
Enter fullscreen mode Exit fullscreen mode

ChromaPanel supports both controlled and uncontrolled usage.

One useful detail is that onChange and onChangeComplete solve different problems.

onChange runs continuously while the user is changing the color.

onChangeComplete runs once when that interaction finishes.

<ColorInput
  value={color}
  onChange={(result) => setColor(result.hex)}
  onChangeComplete={(result) => saveTheme(result.hex)}
/>
Enter fullscreen mode Exit fullscreen mode

That means you can update your UI instantly without making a database request on every tiny movement.

Use onChange for the live experience.

Use onChangeComplete for saving, network calls, history entries, or other expensive work.

Make the React color picker work with forms

This is one feature that often gets ignored when developers add a color picker.

A color picker is still an input.

If it is sitting inside a profile form, settings form, onboarding page, or admin panel, it should work with the rest of that form.

ChromaPanel's ColorInput can behave like a normal form field.

<form action={saveSettings}>
  <label htmlFor="brand-color">
    Brand color
  </label>

  <ColorInput
    id="brand-color"
    name="brandColor"
    defaultValue="#2563eb"
    format="hex"
    required
  />

  <button type="submit">
    Save settings
  </button>
</form>
Enter fullscreen mode Exit fullscreen mode

The value can be submitted with the surrounding form.

It also supports things such as required, disabled, labels, form reset behavior, and different output formats.

You can read the full React color picker form guide if your application relies heavily on native forms or React form libraries.

This is useful for:

settings pages, theme configuration, SaaS dashboards, account customization, CMS interfaces, admin panels, and onboarding flows.

Show the full color picker inline

A popover works well when color is only one field in a larger form.

A design tool is different.

If users are working with color constantly, you probably want the panel to stay visible.

Use ChromaPanel directly.

import { ChromaPanel } from "chroma-panel";

export function ThemeEditor() {
  return (
    <ChromaPanel
      defaultValue="#3366cc"
      modes={["wheel", "sliders", "palettes"]}
      showTitleBar={false}
    />
  );
}
Enter fullscreen mode Exit fullscreen mode

The ChromaPanel component gives you the same color system without hiding it inside a popover.

That works well for theme editors, website builders, design tools, brand editors, graphics applications, product customizers, and other interfaces where color is an important part of the workflow.

Choose the color picker modes you actually need

Not every user chooses color the same way.

Someone may want to explore visually.

Someone else knows the exact RGB value.

Another user only wants to select from approved brand colors.

ChromaPanel provides five different ways to choose a color.

The color wheel gives users a visual way to explore hue and saturation.

The RGB, HSL and HSB sliders provide precise channel-level control.

The palette mode provides searchable predefined colors and can also use your own brand palette.

The pencils mode provides a large 120-color swatch grid.

The image color picker lets users select colors from uploaded images.

You decide which ones should appear.

<ChromaPanel
  modes={[
    "wheel",
    "sliders",
    "palettes",
  ]}
/>
Enter fullscreen mode Exit fullscreen mode

A simple settings page may only need the wheel.

A design tool may need all of them.

A company branding screen may only need an approved palette.

That is better than forcing every user to work with the same large interface.

Add an image color picker to React

This is where color picking becomes much more useful for creative applications.

Imagine a user uploads a logo.

They want the application theme to match that logo.

Instead of making them manually find each HEX value, the application can extract the dominant colors automatically.

ChromaPanel's image mode allows the user to drop, paste, or select an image.

The picker can extract dominant colors and show them as swatches.

The user can also sample an exact pixel.

<ChromaPanel
  modes={["image"]}
  defaultValue="#3366cc"
/>
Enter fullscreen mode Exit fullscreen mode

You can also use the image API without showing the full React color picker.

import { extractPalette } from "chroma-panel";

const { swatches } = await extractPalette(file, {
  maxColors: 8,
});
Enter fullscreen mode Exit fullscreen mode

That opens up other use cases.

You could generate a theme from a company logo.

You could create a palette from a product photograph.

You could extract avatar colors.

You could build image editing tools.

You could automatically suggest colors after a user uploads an asset.

The image sampler uses a bounded, downscaled sampling surface, and a separate worker entry point is available when you want heavier processing away from the main thread.

Add an eyedropper to your React color picker

Sometimes the color already exists somewhere on the screen.

The user simply wants to grab it.

ChromaPanel includes eyedropper support through the browser EyeDropper API.

Where the browser supports it, the user can choose a color from somewhere else on their screen.

This works especially well in:

design tools, website builders, theme editors, graphics applications, and brand customization interfaces.

You can use the eyedropper through the normal picker interface or use the useEyedropper hook when you want to create your own button.

Eyedropper support has also become a common feature in newer React color-picker components, which shows that developers increasingly expect precise screen sampling in advanced color workflows.

Add a gradient color picker

Solid colors are enough for many forms.

They are not enough for every design tool.

For gradients, ChromaPanel provides a separate GradientEditor.

import {
  GradientEditor,
  gradientToCss,
} from "chroma-panel/gradient";
Enter fullscreen mode Exit fullscreen mode

It supports linear and radial gradients.

The gradient editor is separate from the normal color-picker entry point, so an application that only needs solid colors does not need to use the gradient functionality.

Keeping these features separate is useful because a production React color picker should not force every feature into every screen.

Gradient color pickers remain their own active search category in the React ecosystem, especially for design and customization tools.

Work with OKLCH and modern CSS colors

A few years ago, most web color interfaces stopped at:

HEX, RGB, HSL, and HSV.

Modern CSS has moved further.

OKLCH, OKLab, Lab, LCH, and Display P3 are increasingly useful in design systems and modern frontend work.

ChromaPanel includes CSS Color 4 utilities for those workflows.

import {
  parseColor,
  isInGamut,
  mapToGamut,
  serializeColor,
} from "chroma-panel/color";

const color = parseColor(
  "oklch(72% 0.18 250)"
);

if (color && !isInGamut(color, "srgb")) {
  const fallback = mapToGamut(
    color,
    "srgb"
  );

  console.log(
    serializeColor(fallback)
  );
}
Enter fullscreen mode Exit fullscreen mode

These utilities can parse, convert, map, and serialize modern CSS colors.

They do not require the React UI.

That means the color engine can also be useful elsewhere in your application.

OKLCH is becoming a much more visible search topic around modern frontend color tooling, with current color tools and React packages specifically targeting OKLCH, gamut handling, Display P3, and modern design-system workflows.

Accessibility should be part of the color picker

A color picker is naturally visual.

That makes accessibility especially important.

Users should not need a mouse just to change a color.

ChromaPanel's accessibility implementation includes keyboard-operable controls and screen-reader behavior.

Color channels use real range inputs.

Keyboard users can change values with normal input behavior.

Focus is managed when the popover opens and closes.

Swatches have accessible names.

The component also accounts for reduced-motion and forced-color preferences.

Accessibility is also a common selling point in current React color-picker packages, so it is worth treating it as part of the component architecture instead of something added later.

Use ChromaPanel with Next.js

A modern React package also needs to work inside server-rendered applications.

ChromaPanel documents Next.js and server-rendering support.

Browser-dependent parts are separated so the package can be used safely in applications using React server rendering.

If the picker lives inside an interactive Next.js component, you can use it from a client component as expected.

"use client";

import { ColorInput } from "chroma-panel";

export function BrandColorPicker() {
  return (
    <ColorInput
      defaultValue="#3366cc"
    />
  );
}
Enter fullscreen mode Exit fullscreen mode

This makes Next.js color picker another useful search path for developers who are not simply looking for a generic React component.

Use it with Tailwind CSS and shadcn/ui

Many React applications now build their UI around Tailwind CSS or shadcn/ui.

ChromaPanel has a Tailwind CSS styling guide and a dedicated shadcn/ui integration guide.

You are not required to install shadcn, Radix, or another UI library.

But if your application already uses them, you can make your existing Popover, Dialog, or Sheet own the surrounding interface and render ChromaPanel inside.

That matters because shadcn color picker is now a meaningful search category of its own. Current component libraries are publishing color-picker recipes specifically for shadcn and Next.js projects.

Keep your React color picker bundle under control

More features usually mean more JavaScript.

That is why entry points matter.

The full ChromaPanel configuration with all five modes is measured at about 23.1 kB gzipped in the project's Vite production measurement.

The panel shell plus one mode is around 15 kB gzipped.

If you only need one or two modes, import the panel shell and those modes explicitly.

import { ChromaPanel } from "chroma-panel/panel";
import { wheelMode } from "chroma-panel/modes";

export function SmallPicker() {
  return (
    <ChromaPanel
      modes={[wheelMode]}
    />
  );
}
Enter fullscreen mode Exit fullscreen mode

You can read more about ChromaPanel entry points and tree shaking.

This is especially useful when you need the ChromaPanel API but not image picking, palettes, pencils, and every other mode.

When a smaller React color picker is better

More functionality is not automatically better.

If your requirement is simply:

“Let the user choose one HEX color.”

then you may not need image sampling, gradients, OKLCH, an eyedropper, palettes, or a complete color engine.

A smaller React color picker may be the better choice.

For example, react-colorful specifically focuses on providing a small, accessible, zero-dependency core picker. Its current npm documentation describes the picker as about 3.1 kB gzipped.

ChromaPanel makes more sense when your application needs the wider workflow.

The right question is not:

“Which React color picker has the most features?”

It is:

“What will users actually need to do with color in this application?”

A simple React color picker can grow with your app

You may start here:

<ColorInput
  defaultValue="#3366cc"
/>
Enter fullscreen mode Exit fullscreen mode

Six months later, the same product may need:

a controlled color value, brand palettes, image sampling, recent colors, an eyedropper, precise RGB values, gradients, contrast checks, OKLCH, Tailwind tokens, and accessible keyboard controls.

Replacing your color system halfway through a product can create unnecessary work.

The idea behind ChromaPanel is that you can start small and add those capabilities only when you need them.

The package currently provides five color-selection modes, native forms, TypeScript, CSS Color 4 utilities, gradient editing, image sampling, contrast tools, exports, and zero runtime dependencies.

Frequently asked questions

What is a good React color picker for TypeScript?

ChromaPanel includes TypeScript types directly in the package, so you do not need a separate @types package.

You can see the TypeScript documentation for more details.

Can I use a React color picker with Next.js?

Yes. ChromaPanel includes documentation for Next.js and server rendering.

Interactive picker components should be used from the client side of a Next.js application.

Is there a React color picker with an eyedropper?

Yes. ChromaPanel includes eyedropper support where the browser EyeDropper API is available.

Can React pick colors from an image?

Yes. ChromaPanel's image color picker can extract dominant colors from an image and sample an exact pixel.

The extractPalette utility can also be used independently.

Is there a React gradient color picker?

ChromaPanel provides a separate GradientEditor for linear and radial gradient workflows.

Can I use OKLCH in a React color picker?

ChromaPanel's CSS Color 4 tools support OKLCH, OKLab, Lab, LCH, sRGB, and Display P3 workflows.

Does ChromaPanel work with Tailwind CSS?

Yes. There is a dedicated Tailwind CSS guide.

Can I use ChromaPanel with shadcn/ui?

Yes. The shadcn/ui integration guide shows how to use ChromaPanel with an existing shadcn interface.

Final thoughts

A React color picker can be a tiny control or a complete part of your product's design workflow.

For a basic HEX field, keep things simple.

But when users need precise values, palettes, an eyedropper, image sampling, gradients, accessibility, forms, modern CSS color spaces, or design-token workflows, building every part separately can become a much bigger task.

ChromaPanel brings those pieces together behind one React API while still letting you import only the parts you need.

If you want to try it:

Documentation: chroma-panel.jscrate.dev

npm: chroma-panel

GitHub: re-sohail/chroma-panel

The project is open source and released under the MIT license.

If you build something with it, find an issue, or have an idea for improving the React color picker experience, contributions and feedback are welcome.

Top comments (0)