Chroma Panel

Search documentation

Find a page or section

Short answers, each with a link to the page that covers it in full.

These are the questions people ask most often about the chroma-panel React color picker, each answered in a paragraph with a link to the full page.

How do I use the color picker with Next.js?

Install it and import it. The App Router, Remix and other server-rendered setups need no special handling. Every file that needs the browser is marked 'use client', so you do not have to mark your own file just to import it, and nothing reads window at module scope. To keep the markup styled before hydration, import chroma-panel/style.css in your root layout and pass injectStyles={false}. Server rendering has the details.

Does it work with Tailwind CSS?

Yes. Pass utility classes through the classNames prop, one key per part of the panel, such as root, trigger, swatch or slider. The package's styles live in @layer chroma-panel, so with Tailwind v4 you declare the layer order yourself: import chroma-panel/style.css after preflight and before utilities, and your classes win. Colors and sizes are --cp-* CSS variables. Styling with Tailwind shows the exact imports.

Can I use it in a shadcn/ui project?

Yes, as a standalone component. chroma-panel is not built on shadcn/ui or Radix. You install it from npm like any other package, and it needs no provider. It fits a shadcn/ui project the way it fits any Tailwind app: pass your classes through classNames, and set the --cp-* variables to match your theme's colors and radius. The panel follows the system color scheme, so if your app switches dark mode with a class, pass theme="dark" or theme="light" to match. See theming.

How do I get the hex value?

Read it from the change result. onChange and onChangeComplete both receive an object with every format at once, including hex, rgba, hsva and css, whatever you set format to.

import { ColorInput } from "chroma-panel";
 
<ColorInput onChangeComplete={(color) => save(color.hex)} />;

hex is rounded to 8 bits per channel, so store hsva if a color has to come back unchanged. TypeScript lists every field of ColorChangeResult.

How do I use it in a form?

Use ColorInput and give it a name. It submits with the form like a native input, returns to defaultValue on form.reset(), and supports required for native validation. The submitted string follows the format prop, so a form that needs rgba() gets it directly. Pass validationBehavior="aria" if you render your own error messages. If you control the value yourself, resetting it is up to you. Forms has a working example.

Which browsers support the eyedropper?

The eyedropper uses the browser's EyeDropper API, which today means Chromium browsers such as Chrome and Edge. showEyedropper defaults to true, but the button only renders where the API exists, so nothing breaks elsewhere: the button is simply not there. If you build your own trigger, check useEyedropper().supported before rendering it. See browser support and useEyedropper.

Is it written in TypeScript?

Yes. The package ships its own type declarations for both ESM and CommonJS, so there is no @types package to install. Every change handler receives a typed ColorChangeResult, and the prop interfaces ChromaPanelProps and ColorInputProps are exported so you can extend them. Types such as Hsva, Rgba, ColorFormat and ModeId are exported too. TypeScript shows how to type a handler.

How big is the bundle?

Importing chroma-panel with all five modes adds 22.2 kB gzipped to your app. Importing the panel shell and a single mode adds 14.1 kB. Both figures are the increase in a Vite production build, with React external. The package has no dependencies, and react and react-dom are peer dependencies, so it uses the copy your app already has. Entry points shows how to import only the modes you need.

Is the color picker accessible?

Yes, with no extra setup. Every color axis is a real <input type="range">, so keyboard and screen-reader support come from the browser. Arrow keys step, Page Up and Page Down take bigger steps, and Home and End jump to the ends. Values are announced as text, and the popover traps focus, closes on Escape and returns focus to the trigger. Reduced motion and forced-colors mode are handled too. Accessibility covers the details.

Which React versions are supported?

React 16.14 and newer, including 17, 18 and 19. react and react-dom are peer dependencies rather than bundled copies. React DOM is required because the popover renders through createPortal. Both ESM and CommonJS builds are included. The full compatibility table, with browsers and server rendering, is on the about page.

Can I pick colors from an image?

Yes. Image is one of the five built-in modes. Drop an image onto it, or click to choose a file, and it samples the image's dominant colors for you to pick from. Large images are downscaled before they are read, so a big photo never loads in full. Pass imageOptions={{ maxColors: 12 }} to cap the number of colors. To sample images in your own UI, call extractPalette. See image mode.