# ColorPicker **Category**: react **URL**: https://ui.darkcode.dev/en/docs/react/components/color-picker **Source**: https://raw.githubusercontent.com/DarkCode-Developers/darkcode-ui/refs/heads/main/apps/docs/content/docs/en/react/components/(colors)/color-picker.mdx > A composable color picker that synchronizes color value between multiple color components *** ## Import ```tsx import { ColorPicker, ColorArea, ColorSlider, ColorSwatch, ColorField, ColorSwatchPicker, } from '@darkcode-ui/react'; ``` ### Usage ```tsx import {ColorArea, ColorPicker, ColorSlider, ColorSwatch, Label} from "@darkcode-ui/react"; export function Basic() { return ( ); } ``` ### Anatomy The ColorPicker is a composable component that combines multiple color components: ```tsx import { ColorPicker, ColorArea, ColorSlider, ColorSwatch, Label } from '@darkcode-ui/react'; export default () => ( ); ``` ### Controlled ```tsx "use client"; import { Button, ColorArea, ColorField, ColorPicker, ColorSlider, ColorSwatch, ColorSwatchPicker, Label, parseColor, } from "@darkcode-ui/react"; import {Icon} from "@iconify/react"; import {useState} from "react"; export function Controlled() { const [color, setColor] = useState(parseColor("#325578")); const colorPresets = [ "#ef4444", "#f97316", "#eab308", "#22c55e", "#06b6d4", "#3b82f6", "#8b5cf6", "#ec4899", "#f43f5e", ]; const shuffleColor = () => { const randomHue = Math.floor(Math.random() * 360); const randomSaturation = 50 + Math.floor(Math.random() * 50); // 50-100% const randomLightness = 40 + Math.floor(Math.random() * 30); // 40-70% setColor(parseColor(`hsl(${randomHue}, ${randomSaturation}%, ${randomLightness}%)`)); }; return (
{colorPresets.map((preset) => ( ))}

Selected: {color.toString("hex")}

); } ``` ### With Swatches ```tsx import { ColorArea, ColorPicker, ColorSlider, ColorSwatch, ColorSwatchPicker, Label, } from "@darkcode-ui/react"; export function WithSwatches() { const presets = [ "#ef4444", "#f97316", "#eab308", "#22c55e", "#06b6d4", "#3b82f6", "#8b5cf6", "#ec4899", "#f43f5e", ]; return ( {presets.map((preset) => ( ))} ); } ``` ### With Fields Use `ColorField` to allow users to edit individual color channel values with a `Select` to switch between color spaces. ```tsx "use client"; import type {ColorChannel, ColorSpace} from "@darkcode-ui/react"; import { ColorArea, ColorField, ColorPicker, ColorSlider, ColorSwatch, Label, ListBox, Select, } from "@darkcode-ui/react"; import {useState} from "react"; export function WithFields() { const [colorSpace, setColorSpace] = useState("hsl"); const colorChannelsByColorSpace: Record = { hsb: ["hue", "saturation", "brightness"], hsl: ["hue", "saturation", "lightness"], rgb: ["red", "green", "blue"], }; return (
{colorChannelsByColorSpace[colorSpace].map((channel) => ( ))}
); } ``` ### With Sliders Use multiple `ColorSlider` components to adjust each channel of a color value. ```tsx "use client"; import type {ColorChannel, ColorSpace} from "@darkcode-ui/react"; import {ColorPicker, ColorSlider, ColorSwatch, Label, ListBox, Select} from "@darkcode-ui/react"; import {useState} from "react"; export function WithSliders() { const [colorSpace, setColorSpace] = useState("hsl"); const colorChannelsByColorSpace: Record = { hsb: ["hue", "saturation", "brightness", "alpha"], hsl: ["hue", "saturation", "lightness", "alpha"], rgb: ["red", "green", "blue", "alpha"], }; return (
{colorChannelsByColorSpace[colorSpace].map((channel: ColorChannel) => ( // @ts-expect-error - TypeScript can't correlate dynamic colorSpace with channel type ))}
); } ``` ### Eyedropper Add `ColorPicker.EyeDropper` to let users sample a color from anywhere on screen using the native [EyeDropper API](https://developer.mozilla.org/en-US/docs/Web/API/EyeDropper). The button automatically hides where the API is unavailable (set `unsupportedBehavior="disable"` to render it disabled instead). Place it inside the `Popover`, never inside the `Trigger`. ```tsx "use client"; import {ColorArea, ColorPicker, ColorSlider, ColorSwatch, Label} from "@darkcode-ui/react"; export function WithEyeDropper() { return (
); } ``` ### Recent colors Set `recordHistory` on the root and drop in `ColorPicker.Recent` to show a persisted row of recently used colors. History is stored in `localStorage` and powered by the [`useColorHistory`](#usecolorhistory) hook. ```tsx "use client"; import {ColorArea, ColorPicker, ColorSlider, ColorSwatch, Label} from "@darkcode-ui/react"; const recentColors = ["#ef4444", "#f97316", "#eab308", "#22c55e", "#3b82f6", "#8b5cf6"]; export function WithRecent() { return ( ); } ``` ### Copy to clipboard `ColorPicker.CopyButton` copies the current color (hex by default) and shows a transient check. Pass `format` to copy `rgb`, `hsl`, `hexa`, etc. ```tsx "use client"; import {ColorArea, ColorPicker, ColorSlider, ColorSwatch, Label} from "@darkcode-ui/react"; export function WithCopy() { return (
); } ``` ## Related Components - **ColorArea**: 2D color picker for selecting colors from a gradient area - **ColorWheel**: Circular slider for selecting the hue of a color - **ColorSlider**: Slider for adjusting individual color channel values ## Styling ### Passing Tailwind CSS classes ```tsx import { ColorPicker, ColorArea, ColorSlider, ColorSwatch, Label } from '@darkcode-ui/react'; function CustomColorPicker() { return ( ); } ``` ### Customizing the component classes To customize the ColorPicker component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes). ```css @layer components { .color-picker { @apply inline-flex; } .color-picker__trigger { @apply inline-flex items-center gap-4 rounded-lg; } .color-picker__popover { @apply p-4 rounded-xl; } } ``` DarkCode UI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize. ### CSS Classes The ColorPicker component uses these CSS classes ([View source styles](https://github.com/DarkCode-Developers/darkcode-ui/blob/main/packages/styles/components/color-picker.css)): #### Base Classes - `.color-picker` - Base container - `.color-picker__trigger` - Trigger button - `.color-picker__popover` - Popover container ### Interactive States The component supports both CSS pseudo-classes and data attributes for flexibility: - **Focus**: `:focus-visible` or `[data-focus-visible="true"]` - **Disabled**: `:disabled` or `[data-disabled="true"]` ## API Reference ### ColorPicker Props Inherits from [React Aria ColorPicker](https://react-spectrum.adobe.com/react-aria/ColorPicker.html). | Prop | Type | Default | Description | |------|------|---------|-------------| | `value` | `string \| Color` | - | The current color value (controlled) | | `defaultValue` | `string \| Color` | - | The default color value (uncontrolled) | | `onChange` | `(color: Color) => void` | - | Handler called when the color changes | | `recordHistory` | `boolean` | `false` | Track the committed color in a recent-colors history (consumed by `ColorPicker.Recent`) | | `historyOptions` | `UseColorHistoryOptions` | - | Options forwarded to the underlying `useColorHistory` hook | | `children` | `React.ReactNode` | - | Content of the color picker (Trigger, Popover, etc.) | | `className` | `string` | - | Additional CSS classes | ### ColorPicker.Trigger Props | Prop | Type | Default | Description | |------|------|---------|-------------| | `children` | `React.ReactNode \| ((renderProps) => React.ReactNode)` | - | Trigger content or render prop | | `className` | `string` | - | Additional CSS classes | ### ColorPicker.Popover Props | Prop | Type | Default | Description | |------|------|---------|-------------| | `placement` | `Placement` | `"bottom left"` | Placement of the popover | | `children` | `React.ReactNode` | - | Popover content | | `className` | `string` | - | Additional CSS classes | ### ColorPicker.EyeDropper Props Wraps React Aria [Button](https://react-spectrum.adobe.com/react-aria/Button.html). Must be placed inside the `Popover`. | Prop | Type | Default | Description | |------|------|---------|-------------| | `unsupportedBehavior` | `'hide' \| 'disable'` | `'hide'` | What to do where the EyeDropper API is unavailable | | `children` | `React.ReactNode` | - | Override the icon/content | ### ColorPicker.CopyButton Props | Prop | Type | Default | Description | |------|------|---------|-------------| | `format` | `'hex' \| 'hexa' \| 'css' \| 'rgb' \| 'hsl' \| 'hsb' \| ((color: Color) => string)` | `'hex'` | The value copied to the clipboard | | `uppercase` | `boolean` | `true` | Uppercase the value for hex formats | | `children` | `React.ReactNode \| (({ copied }) => React.ReactNode)` | - | Override the button content | ### ColorPicker.Recent Props | Prop | Type | Default | Description | |------|------|---------|-------------| | `colors` | `string[]` | - | Explicit colors; falls back to the ColorPicker history | | `onColorSelect` | `(color: string) => void` | - | Called on select; defaults to applying the color | | `label` | `React.ReactNode` | - | Optional heading above the swatches | | `size` | `'xs' \| 'sm' \| 'md'` | `'xs'` | Swatch size | ### Hooks These reusable hooks power the parts above and can be used standalone. #### useColorHistory `useColorHistory({ storageKey?, maxLength?, colors?, defaultColors?, onChange? }) → { colors, addColor, clear }`. Tracks recently used colors in `localStorage` (deduped, newest first, capped at `maxLength`, default `8`). Pass `storageKey: null` to keep history in memory only. #### useEyeDropper `useEyeDropper({ onResult?, onError? }) → { isSupported, isOpen, open }`. Feature-detects and opens the native EyeDropper. `isSupported` is `false` during SSR and on unsupported browsers. #### useClipboard `useClipboard({ timeout? }) → { copy, copied, error }`. Copies text with a transient `copied` flag that resets after `timeout` ms (default `2000`). ### Related Types #### Color Represents a color value. See [React Aria Color](https://react-spectrum.adobe.com/react-aria/ColorPicker.html#color) for full API. | Method | Description | |--------|-------------| | `toString(format)` | Converts the color to a string in the given format (hex, rgb, hsl, hsb, css) | | `toFormat(format)` | Converts the color to the given format and returns a new Color object | | `getChannelValue(channel)` | Returns the numeric value for a given channel | | `withChannelValue(channel, value)` | Sets the numeric value for a channel and returns a new Color | #### parseColor ```tsx import { parseColor } from 'react-aria-components'; // Parse from string const color = parseColor('#ff0000'); const hslColor = parseColor('hsl(0, 100%, 50%)'); ```