@transience/color-picker
v0.2.1
Published
A modern color picker component with support for OKLCH color space.
Downloads
479
Maintainers
Readme
Color Picker
A modern, OKLCH-first React/Tailwind color picker.
- 🎨 OKLCH-first: Native OKLCH 2D panel with P3 gamut awareness.
- 🌈 Multi-mode: Switch between OKLCH, HSL, and RGB color spaces.
- 🎯 Slot styling: Every internal element accepts className overrides via a typed
classNamesmap. - 🚨 Gamut-aware: Warns when an OKLCH color falls outside the sRGB gamut.
Setup
npm i @transience/color-pickerStyled with Tailwind CSS utilities - no stylesheet ships.
Your app's Tailwind build must scan the package's compiled source so the utilities are included in the generated CSS.
Tailwind v4 (CSS-first):
@import "tailwindcss";
@source "../node_modules/@transience/color-picker/dist";Tailwind v3 (tailwind.config.js):
/** @type {import('tailwindcss').Config} */
export default {
content: [
'./src/**/*.{js,jsx,ts,tsx}',
'./node_modules/@transience/color-picker/dist/**/*.{js,cjs}',
],
theme: { extend: {} },
plugins: [],
};If you are using pnpm, you need to add the following line to your .npmrc file to hoist our packages to the root node_modules.
public-hoist-pattern[]=*@transience/color-picker/*After modifying the .npmrc file, you need to run pnpm install again to ensure that the dependencies are installed correctly.
Usage
import { ColorPicker } from '@transience/color-picker';
import { useState } from 'react';
export function Example() {
const [color, setColor] = useState('oklch(0.7 0.15 250)');
return <ColorPicker color={color} onChange={setColor} />;
}color accepts any CSS color string (#ff0044, rgb(...), hsl(...), oklch(...), named colors, etc.) — parsed via colorizr.
See the Storybook demo for layout variants and every prop combination.
Props
| Prop | Type | Default |
|------------------------------------------------------------------------------------------------------------------------------------------------| --- | --- |
| channelsPer-channel toggles: hidden, disabled.Keys irrelevant to the active mode are ignored. | ChannelsConfig | — |
| classNamesSlot-based className overrides for every internal part. See Styling. | ColorPickerClassNames | — |
| labelsSlot-based text/aria overrides per component. Each rendered component reads only its own slot. | ColorPickerLabels | — |
| colorControlled color value. Any CSS color string.Falls back to the internal default when undefined. | string | 'oklch(54% 0.194 250)' |
| defaultModeInitial mode for the 2D panel and channel controls. | 'oklch' \| 'hsl' \| 'rgb' | 'oklch' |
| displayFormatInitial text format for the ColorInput. 'auto' → 'oklch' in OKLCH mode, else 'hex'. | ColorFormat | 'auto' |
| modesModes shown in the mode switcher. | ColorMode[] | ['oklch', 'hsl', 'rgb'] |
| onChangeCalled on every color change. Format follows the resolved outputFormat. | (value: string) => void | — |
| onChangeModeCalled when the user flips the mode via the switcher. | (mode: ColorMode) => void | — |
| outputFormatInitial format onChange emits. 'auto' follows the resolved displayFormat. | ColorFormat | 'auto' |
| precisionDecimal digits for non-hex output. Ignored for hex. | number | 5 |
| showAlphaRenders an alpha slider and appends alpha to emitted values when < 1. | boolean | false |
| showColorInputShows the text color input with the current value formatted per displayFormat. | boolean | true |
| showEyeDropperAdds a screen color picker button. Silently omitted in browsers without window.EyeDropper (currently Chromium-only). | boolean | true |
| showGlobalHueShows the global (mode-independent) hue slider in the toolbar. | boolean | false |
| showInputsShows numeric input fields per channel. Inline when showSliders is on, standalone row otherwise. | boolean | true |
| showModeSelectorShows the OKLCH/HSL/RGB mode switcher. | boolean | true |
| showPanelShows the 2D color panel (saturation/value for HSL/RGB, chroma/lightness for OKLCH). | boolean | true |
| showSettingsAdds a ⋮ menu to expose display and output format choices to end users. | boolean | false |
| showSlidersShows the per-channel sliders matching the active mode (L/C/H, H/S/L, or R/G/B). | boolean | true |
| showSwatchShows the circular color preview next to the color input. | boolean | true |
Color modes and formats
ColorMode—'oklch' | 'hsl' | 'rgb'. Drives the 2D panel, mode switcher, and which channel slider/input set is rendered.ColorFormat—'auto' | 'hex' | 'hsl' | 'oklab' | 'oklch' | 'rgb'. Used for bothdisplayFormat(text input value) andoutputFormat(whatonChangeemits).
'auto' resolves against the active mode: OKLCH mode → 'oklch', otherwise 'hex'. outputFormat defaults to following the resolved displayFormat, so the emitted string matches what the user sees unless you set them independently.
When an OKLCH color doesn't fit inside a narrow format (hex, hsl, rgb), a gamut warning icon appears inside the color input.
Styling
Every overridable part is exposed via the ColorPickerClassNames slot map (see src/types.ts). Each slot's classes are merged with the component's defaults via tailwind-merge, so your overrides win predictably — classNames={{ swatch: { root: 'rounded-full' } }} reliably overrides the internal rounded-md. Without that merge, both classes would land in the DOM and CSS source order would decide the winner.
Most Tailwind apps already ship tailwind-merge, so it dedupes in your bundle. If yours doesn't, it's pulled in automatically with this package.
<ColorPicker
color={color}
onChange={setColor}
classNames={{
root: 'border border-neutral-300 rounded-lg',
swatch: { root: 'ring-2 ring-offset-2' },
hueSlider: { track: 'h-3' },
modeSelector: {
button: 'first:rounded-none last:rounded-none text-sm',
},
}}
/>Exports
Individual parts are also exported as standalone widgets — drop a swatch, alpha slider, or mode switcher anywhere in your UI.
| Export | Purpose |
|---------------------|-----------------------------------------------------------------------------|
| ColorPicker | The full picker. |
| useColorPicker | State hook powering ColorPicker. See Hook. |
| AlphaSlider | Checkerboard-backed alpha slider. |
| ChannelInputs | Per-mode input group (L/C/H, H/S/L, or R/G/B). |
| ChannelSliders | Per-mode slider group (L/C/H, H/S/L, or R/G/B). |
| ColorInput | CSS color string input with validation. |
| EyeDropper | Screen color picker button (omits when window.EyeDropper is unavailable). |
| GamutWarning | Popover-anchored icon shown when an OKLCH color falls outside sRGB. |
| GradientSlider | Low-level 1D slider with a CSS-gradient track. |
| HueSlider | Standalone mode-aware hue slider (OKLCH or HSL gradient). |
| ModeSelector | OKLCH / HSL / RGB mode switcher. |
| OKLCHPanel | 2D OKLCH chroma/lightness panel with sRGB gamut overlay. |
| SaturationPanel | 2D HSV saturation/value panel (used for HSL and RGB modes). |
| SettingsMenu | Display/output format picker popover. |
| Swatch | Circular color preview over a checkerboard. Accepts children for icon overlays. |
The constants (hslHueGradient, oklchHueGradient) and all types (ColorPickerProps, UseColorPickerReturn, ColorMode, ColorFormat, OklchColor, HSV, ChannelsConfig, ColorPickerClassNames, etc.) are also exported.
Hook
The useColorPicker hook is the state engine behind the ColorPicker component. It accepts the same props but doesn't render any UI — just returns the state and callbacks needed to build your own custom picker layout or embed the controls inside an existing design.
Reach for it when you need a custom layout, a partial picker, or want to embed the controls inside an existing UI shell.
import { useColorPicker } from '@transience/color-picker';
const picker = useColorPicker({ color, onChange: setColor });See docs/HOOK.md for the full return reference, composition map, and working examples.
Color engine
Color parsing, conversion, gamut math, and output formatting are powered by colorizr (same author). Whatever you pass to color is parsed by it; whatever onChange emits is formatted by it. It ships as a runtime dependency — no install needed.
If you build a custom layout with useColorPicker and need color utilities beyond what the hook returns (e.g., darken, lighten, contrast, extractColors), install it directly:
npm i colorizrIt'll dedupe in your bundle.
References
- css-color-component
- oklume
- react-color
- Chrome DevTools color picker (built-in reference for UX and features)
License
MIT
