# FAQ

> Answers to common questions about the chroma-panel React color picker: Next.js, Tailwind, shadcn/ui, forms, TypeScript, bundle size and browser support.

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

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](https://chroma-panel.jscrate.dev/react/handbook/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](https://chroma-panel.jscrate.dev/react/handbook/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](https://chroma-panel.jscrate.dev/react/handbook/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.

```tsx
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](https://chroma-panel.jscrate.dev/react/handbook/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](https://chroma-panel.jscrate.dev/react/handbook/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](https://chroma-panel.jscrate.dev/react/handbook/browser-support) and
[useEyedropper](https://chroma-panel.jscrate.dev/react/utils/use-eyedropper).

## 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](https://chroma-panel.jscrate.dev/react/handbook/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](https://chroma-panel.jscrate.dev/react/utils/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](https://chroma-panel.jscrate.dev/react/overview/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](https://chroma-panel.jscrate.dev/react/overview/about#compatibility) 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](https://chroma-panel.jscrate.dev/react/modes/image).
