A developer-friendly color picker component with TypeScript support, multiple interactive variants, and extensive customization options.
Live demo: https://color-picker.zenui.net/
- Features
- Installation
- Quick Start
- Usage Examples
- API Reference
- Theming & Customization
- Compatibility / Requirements
- FAQ
- Contributing
- License
- Support
- Multiple color formats: hex, rgb, hsl, hsv, cmyk
- Interactive variants:
- Wheel picker
- Hue slider
- Hue box
- Brightness/Value slider and fine-grained inputs
- Format switcher and copy-friendly output
- Favorites and quick presets
- Color history and reset
- Light/Dark themes with custom theme support
- Fully typed with TypeScript
- Accessible, keyboard-friendly interactions
- Small and tree-shakeable
Using npm:
npm install @zenuilabs/color-picker-react
import React, {useState} from 'react'; import {ColorPicker} from '@zenuilabs/color-picker-react'; export default function App() { const [color, setColor] = useState('#3B82F6'); return ( <div> <ColorPicker value={color} format="hex" variant="wheel" onChange={(next) => setColor(next.hex)} /> <p>Selected: {color}</p> </div> ); }
Basic (HEX, wheel):
import React, {useState} from 'react'; import {ColorPicker} from '@zenuilabs/color-picker-react'; function BasicExample() { const [color, setColor] = useState('#4F46E5'); return ( <ColorPicker value={color} format="hex" variant="wheel" onChange={(val) => setColor(val.hex)} /> ); }
Use picker as inline:
import React, {useState} from 'react'; import {ColorPicker} from '@zenuilabs/color-picker-react'; function BasicExample() { const [color, setColor] = useState('#4F46E5'); return ( <ColorPicker value={color} format="hex" inline={true} // now the picker will render as inline variant="wheel" onChange={(val) => setColor(val.hex)} /> ); }
Change format and access multiple representations:
import React, {useState} from 'react'; import {ColorPicker, type ColorFormat} from '@zenuilabs/color-picker-react'; function FormatExample() { const [format, setFormat] = useState<ColorFormat>('rgb'); const [value, setValue] = useState('#22C55E'); return ( <div> <ColorPicker value={value} format={format} variant="hue-slider" onChange={(val, fmt) => { // Persist a specific representation setValue(fmt === 'hex' ? val.hex : val.hex); // You can also handle the active format setFormat(fmt); console.log('As HEX:', val.hex); console.log('As RGB:', val.rgb); console.log('As HSL:', val.hsl); console.log('As HSV:', val.hsv); console.log('As CMYK:', val.cmyk); }} /> </div> ); }
Hue box variant with presets, alpha, and history:
import React, {useState} from 'react'; import {ColorPicker} from '@zenuilabs/color-picker-react'; const presetColors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#F7B267', '#A78BFA']; function AdvancedExample() { const [color, setColor] = useState('#F59E0B'); return ( <ColorPicker value={color} format="hsl" variant="hue-box" showAlpha showHistory showFormats showCopyButton presetColors={presetColors} maxHistory={15} onChange={(val) => setColor(val.hex)} /> ); }
A controlled React component. Provide a value
and handle updates via onChange
.
Props:
Prop | Type | Default | Description |
---|---|---|---|
value | string or ColorValue | — | Current color value (commonly HEX like #ffffff ). |
format | ColorFormat | 'hex' | Active display/parse format: 'hex', 'rgb', 'hsl', 'hsv', or 'cmyk'. |
variant | ColorPickerVariant | 'wheel' | Visual variant: 'wheel', 'hue-slider', or 'hue-box'. |
theme | Themes or ColorPickerTheme | 'light' | Built-in theme ('light' or 'dark'). |
disabled | boolean | false | Disable all interactions. |
showAlpha | boolean | true | Enable alpha channel control and display when supported. |
showHistory | boolean | true | Track and display recently picked colors. |
showTitle | boolean | true | Show a title of the picker. |
showFormats | boolean | true | Show the format selector (HEX/RGB/HSL/HSV/CMYK). |
showCopyButton | boolean | true | Show a one-click copy to clipboard for the active format. |
presetColors | string[] | defaultPresetColors | Quick-access swatches displayed below the picker. |
maxHistory | number | 10 | Maximum number of items kept in color history. |
containerClasses | string | '' | Additional CSS classes for the root element. |
showColorInput | boolean | true | Show an input field to enter color values manually. |
containerStyle | React.CSSProperties | — | Inline styles for the root element. |
popupClasses | string | — | Additional CSS classes for the popup/colorContainer element. |
onChange | (value: ColorValue, format: ColorFormat) => void | — | Called on any color change. |
inline | boolean | false | Render the picker inline rather than in a popup. |
title | string | 'Color Picker' | Title text displayed on the picker. |
enableHueSlider | boolean | false | Enable the hue slider for variant that supports it. |
showPresets | boolean | true | Show preset color swatches. |
onFormatChange | (format: ColorFormat) => void | — | Called when the active format changes. |
onOpen | () => void | — | Callback fired when the color picker opens. |
brandColor | string | — | Optional brand color used for styling or highlighting. |
enableFavorite | boolean | false | Enable marking colors as favorites. |
enableShuffle | boolean | false | Enable shuffle button for random colors. |
onClose | () => void | — | Callback fired when the color picker closes. |
triggerRef | React.RefObject | — | External reference to trigger the picker popup. |
showDefaultButton | boolean | true | Show the default triggering button. |
Notes:
ColorValue
includes every representation of the color (HEX, RGB, HSL, HSV, CMYK) so you can store or display any format without re-conversion.- The component is designed to be controlled; keeping
value
in your state is recommended.
export type ColorFormat = 'hex' | 'rgb' | 'hsl' | 'hsv' | 'cmyk'; export type ColorPickerVariant = 'wheel' | 'hue-slider' | 'hue-box' export type Themes = 'light' | 'dark'; export interface ColorValue { hex: string; rgb: { r: number; g: number; b: number; a?: number }; hsl: { h: number; s: number; l: number; a?: number }; hsv: { h: number; s: number; v: number; a?: number }; cmyk: { c: number; m: number; y: number; k: number }; } export interface ColorPickerTheme { primary: string; secondary: string; background: string; surface: string; text: string; textSecondary: string; border: string; borderHover: string; shadow: string; } export interface ColorPickerProps { value?: string; format?: ColorFormat; variant?: ColorPickerVariant; theme?: Themes; disabled?: boolean; inline?: boolean; showColorInput?: boolean; showTitle?: boolean; title?: string popupClasses?: string; showAlpha?: boolean; showHistory?: boolean; showFormats?: boolean; showCopyButton?: boolean; presetColors?: string[]; maxHistory?: number; containerClasses?: string; containerStyle?: React.CSSProperties; onChange?: (color: ColorValue, format: ColorFormat) => void; onFormatChange?: (format: ColorFormat) => void; onOpen?: () => void; onClose?: () => void; enableHueSlider?: boolean; brandColor?: string; enableFavorite?: boolean; showPresets?: boolean; enableShuffle?: boolean; triggerRef?: React.RefObject<HTMLElement>; showDefaultButton?: boolean; } export interface UseColorPickerOptions { initialColor?: string; initialFormat?: ColorFormat; showAlpha?: boolean; maxHistory?: number; }
Useful helpers are available for parsing and formatting colors.
import { parseColor, formatColorValue, colorToValue, hsvToRgb, defaultPresetColors, type ColorValue, type ColorFormat, } from '@zenuilabs/color-picker-react';
parseColor(input: string): ColorValue
— Parses a string (HEX, RGB, HSL, etc.) into a fullColorValue
.formatColorValue(value: ColorValue, format: ColorFormat): string
— Converts aColorValue
to a formatted string.colorToValue(input: string | ColorValue): ColorValue
— Normalizes arbitrary input to aColorValue
.hsvToRgb(h: number, s: number, v: number): { r: number; g: number; b: number }
— Low-level conversion utility.defaultPresetColors: string[]
— A ready-to-use list of common swatches.
You can switch between built-in themes.
Built-in theme:
<ColorPicker theme="dark"/>
Presets:
<ColorPicker presetColors={['#FF6B6B', '#4ECDC4', '#45B7D1']}/>
Alpha channel:
<ColorPicker showAlpha format="rgb"/>
History and favorites:
<ColorPicker showHistory showFavorites maxHistory={12}/>
- React: 16.8 or newer (Hooks support required; 18+ recommended)
- TypeScript: 5.x recommended (type definitions included)
- Node.js: 18+ recommended
- Module format: ESM-first
- Browsers: Modern browsers with standard Canvas and Pointer Events support
⚠️ Note: Advanced features may rely on newer web APIs. Ensure your target browsers support them.
- Controlled vs. uncontrolled?
- The component is designed for controlled usage via
value
andonChange
.
- The component is designed for controlled usage via
- How to store colors?
- Store
ColorValue
if you need multiple formats. Otherwise, store a single string (e.g.,hex
) and derive other formats when necessary.
- Store
- Can I disable certain UI parts?
- Use the boolean props like
showFormats
,showCopyButton
,showHistory
, etc., to tailor the UI.
- Use the boolean props like
Contributions are welcome!
- Fork the repository
- Create a feature branch
- Commit your changes with clear messages
- Add/adjust tests where applicable
- Submit a pull request describing your changes and rationale
Before submitting:
- Ensure linting and type checks pass
- Ensure the demo/playground still works
- Update documentation if props or behavior changed
- Issues: open a ticket at https://github.com/zenui-labs/zenui-color-picker/issues/new
- Contact: create an issue with details or reach us via your preferred channel
This package ships with first-class TypeScript support. Types can be imported directly:
import type { ColorFormat, ColorValue, ColorPickerVariant, ColorPickerTheme, } from '@zenuilabs/color-picker-react';
- The package is published on npm as
@zenuilabs/color-picker-react
. - ESM build with tree-shaking-friendly structure.
- CSS: no global stylesheet required; theming is provided via props and CSS variables.