# React color picker tutorial

> Build a React color picker with useState, handle live and committed changes, submit the value in a form, and choose the right picker layout.

Source: https://chroma-panel.jscrate.dev/react/overview/tutorial
Last updated: 2026-09-21

This guide builds a controlled React color picker from a few lines of code. You
will keep the value in `useState`, update the preview while someone drags, and
save the final color when the interaction ends.

## Install

```bash
npm install chroma-panel
```

No provider is required. The component loads its own styles, so you can render
it as soon as the package is installed.

## Add a color picker to a React app

Use `ColorInput` when the picker belongs in a form, settings page, or toolbar.
It renders a color swatch button and opens the panel in a responsive popover.

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

export function AccentColorPicker() {
  const [color, setColor] = useState("#3366cc");

  return (
    <ColorInput
      value={color}
      onChange={(next) => setColor(next.hex)}
      aria-label="Accent color"
    />
  );
}
```

`value` makes the component controlled. If you do not need the value in React
state, replace `value` with `defaultValue` and remove `onChange`.

## Handle onChange and save after the drag

`onChange` runs while the pointer or keyboard changes the color. It is useful
for a live preview. `onChangeComplete` runs once at the end, which makes it a
better place for storage, undo history, analytics, or a network request.

```tsx
<ColorInput
  value={color}
  onChange={(next) => setColor(next.hex)}
  onChangeComplete={(next) => saveTheme({ accent: next.hex })}
/>
```

Both callbacks receive hex, RGB, HSL, HSV, alpha, and CSS string values. Read
the format your app stores. See [controlled and uncontrolled
state](https://chroma-panel.jscrate.dev/react/handbook/controlled) for the full event model.

## Put the picker on the page

Use `ChromaPanel` when the color picker should stay visible. It is the same
picker without the trigger and popover.

```tsx
import { ChromaPanel } from "chroma-panel";

<ChromaPanel
  value={color}
  onChange={(next) => setColor(next.hex)}
  modes={["wheel", "sliders", "palettes"]}
/>;
```

Pass only the modes your task needs. A design tool may need sliders and image
sampling, while a theme setting may need only approved palette swatches.

## Submit the color in a form

Give `ColorInput` a `name` to include its value in `FormData`. `required`,
`disabled`, and `form.reset()` work as they do on other form controls.

```tsx
<form action={saveProfile}>
  <label htmlFor="profile-color">Profile color</label>
  <ColorInput
    id="profile-color"
    name="profileColor"
    defaultValue="#3366cc"
    format="hex"
    required
  />
  <button type="submit">Save</button>
</form>
```

Read the [forms guide](https://chroma-panel.jscrate.dev/react/handbook/forms) for validation, reset behavior,
and React Hook Form options.

## Choose a starting point

- Use [ColorInput](https://chroma-panel.jscrate.dev/react/components/color-input) for a popover or dropdown
  color picker.
- Use [ChromaPanel](https://chroma-panel.jscrate.dev/react/components/chroma-panel) for an inline panel or a
  color picker inside a modal.
- Use the [wheel](https://chroma-panel.jscrate.dev/react/modes/wheel) for visual picking and
  [sliders](https://chroma-panel.jscrate.dev/react/modes/sliders) for exact RGB, HSL, HSV, or opacity values.
- Use [palettes](https://chroma-panel.jscrate.dev/react/modes/palettes) for brand colors and
  [image mode](https://chroma-panel.jscrate.dev/react/modes/image) to pick colors from an uploaded image.
- Use [GradientEditor](https://chroma-panel.jscrate.dev/react/components/gradient-editor) when the value is a
  linear or radial gradient instead of one color.

For framework setup, continue with [Next.js](https://chroma-panel.jscrate.dev/react/frameworks/next-js),
[Vite](https://chroma-panel.jscrate.dev/react/frameworks/vite), or [Remix](https://chroma-panel.jscrate.dev/react/frameworks/remix).
