@markoradak/color-picker
Compound-component React color picker and gradient editor. Composable, accessible, tree-shakeable. forwardRef and HTML props on all components.
npm install @markoradak/color-pickerPlayground
Configure the color picker interactively and copy the generated code.
Preview
Options
CSS Output
radial-gradient(circle at 23.84% 26.6%, #16db89 0%, rgba(22, 219, 137, 0) 50%), radial-gradient(circle at 66% 84.25%, #16db897f 0%, rgba(22, 219, 137, 0) 50%), radial-gradient(circle at 81.36% 54.36%, #16db8926 0%, rgba(22, 219, 137, 0) 50%), #e7fff5Generated Code
import { ColorPickerInline } from "@markoradak/color-picker/presets";
import type { ColorPickerValue } from "@markoradak/color-picker";
function MyColorPicker() {
const [value, setValue] = useState<ColorPickerValue>("#16db89");
return (
<ColorPickerInline
value={value}
onValueChange={setValue}
contrastColor="#ffffff"
onContrastColorChange={(c) => console.log(c)}
/>
);
}Features
Compound Components
Radix-style composable API with forwardRef on all components and full HTML props spreading. Pick only the parts you need and arrange them however you want.
Gradient Editor
Linear, radial, conic, and mesh gradients with interactive stop editing, angle controls, type switching, and a discriminated union type system.
Solid Colors
Full HEX, RGB, and HSL support with format toggling, validated input, and automatic formatting.
Mode Selector
Built-in toggle between solid and gradient modes. One value type handles both.
Eye Dropper
Native browser color sampling via the EyeDropper API with graceful fallback when unsupported.
Color Tokens
Named color tokens with automatic matching, searchable dropdown, and keyboard navigation. Pass your own tokens or let autoTokens detect CSS custom properties automatically.
Preset Swatches
Solid color swatches and gradient swatches with keyboard navigation and active state indicators.
Alpha Support
Full opacity control with alpha slider. Checkerboard pattern for transparency preview.
WCAG Contrast Checking
Built-in contrast-ratio readout, AA/AAA badge, and a threshold curve drawn across the saturation/brightness area so users can see which colors pass. Exposed as both composable components and a preset prop.
Pre-composed Presets
ColorPickerPopover and ColorPickerInline for common layouts. Import from /presets sub-path.
CSS Theming
Style every part with CSS custom properties. Ships a default theme with light and dark modes.
Accessible
Full keyboard navigation, ARIA labels, screen reader support, and reduced-motion respect. Built on Radix UI primitives. Concurrent Mode safe.
Tree-shakeable
ESM + CJS dual builds with optimized re-render performance. Import only what you use. Only CSS files have side effects.
Code Examples
Compound Component Popover
Trigger button opens a popover with composable color picker controls. Built on Radix Popover.
import {
ColorPicker,
ColorPickerArea,
ColorPickerHueSlider,
ColorPickerAlphaSlider,
ColorPickerInput,
ColorPickerEyeDropper,
ColorPickerModeSelector,
ColorPickerTrigger,
ColorPickerContent,
} from "@markoradak/color-picker";
function MyColorPicker() {
const [color, setColor] = useState("#3b82f6");
return (
<ColorPicker value={color} onValueChange={setColor}>
<ColorPickerTrigger />
<ColorPickerContent>
<ColorPickerModeSelector />
<ColorPickerArea />
<ColorPickerHueSlider />
<ColorPickerAlphaSlider />
<ColorPickerInput />
<ColorPickerEyeDropper />
</ColorPickerContent>
</ColorPicker>
);
}Gradient Editor
Pass a gradient value to enable gradient mode with stop editing, type switching, and angle controls.
import {
ColorPicker,
ColorPickerGradientEditor,
ColorPickerGradientSwatches,
ColorPickerModeSelector,
toCSS,
} from "@markoradak/color-picker";
import type { ColorPickerValue } from "@markoradak/color-picker";
function MyGradientPicker() {
const [value, setValue] = useState<ColorPickerValue>({
type: "linear",
angle: 90,
stops: [
{ id: "1", color: "#3b82f6", position: 0 },
{ id: "2", color: "#ec4899", position: 100 },
],
});
return (
<ColorPicker value={value} onValueChange={setValue}>
<ColorPickerModeSelector />
<ColorPickerGradientEditor />
<ColorPickerGradientSwatches values={[...]} />
<div style={{ background: toCSS(value) }} />
</ColorPicker>
);
}Color Tokens
Pass named color tokens to the root provider. The input shows a badge when the current color matches a token and a searchable dropdown to browse all tokens. CSS custom properties are auto-detected by default — set autoTokens={false} to disable.
import {
ColorPicker,
ColorPickerArea,
ColorPickerHueSlider,
ColorPickerInput,
} from "@markoradak/color-picker";
// Pass named tokens — the input shows a badge when the color matches
const tokens = {
primary: "#3b82f6",
danger: "#ef4444",
success: "#22c55e",
warning: "#f59e0b",
};
function MyColorPicker() {
const [color, setColor] = useState("#3b82f6");
return (
// autoTokens auto-detects CSS custom properties (enabled by default).
// Set autoTokens={false} to disable auto-detection and use only manual tokens.
<ColorPicker value={color} onValueChange={setColor} tokens={tokens}>
<ColorPickerArea />
<ColorPickerHueSlider />
<ColorPickerInput enableTokenSearch />
</ColorPicker>
);
}WCAG Contrast Checking
Pass a contrastColor to render the contrast-ratio readout, WCAG level badge, and a threshold curve across the color area.
import { useState } from "react";
import { ColorPickerPopover } from "@markoradak/color-picker/presets";
function AccessibleColorPicker() {
const [color, setColor] = useState("#16db89");
const [bg, setBg] = useState("#ffffff");
// Pass contrastColor to enable the WCAG readout + threshold curve.
// onContrastColorChange lets users swap the reference color via the popover.
return (
<ColorPickerPopover
value={color}
onValueChange={setColor}
contrastColor={bg}
onContrastColorChange={setBg}
/>
);
}Pre-composed Preset
ColorPickerInline from /presets for a quick inline picker with all features enabled.
import { ColorPickerInline } from "@markoradak/color-picker/presets";
function QuickPicker() {
const [color, setColor] = useState("#16db89");
return (
<ColorPickerInline
value={color}
onValueChange={setColor}
/>
);
}API Reference
Components
| Component | Description |
|---|---|
| ColorPicker | Root provider and context. Accepts tokens and autoTokens props. |
| ColorPickerProvider | Headless provider without Radix Popover (for custom layouts) |
| ColorPickerTrigger | Popover trigger button with color swatch |
| ColorPickerInputTrigger | Input-style trigger with inline editing and token badge |
| ColorPickerContent | Popover content wrapper with portal support |
| ColorPickerModeSelector | Solid/gradient mode radio group toggle |
| ColorPickerModeSelectorItem | Individual mode option (solid, linear, radial, conic, mesh) |
| ColorPickerArea | Saturation/brightness 2D area |
| ColorPickerAreaGradient | Area background gradient layer (sub-component) |
| ColorPickerAreaThumb | Area draggable thumb (sub-component) |
| ColorPickerHueSlider | Hue selection slider |
| ColorPickerHueSliderTrack | Hue slider rainbow track (sub-component) |
| ColorPickerHueSliderThumb | Hue slider draggable thumb (sub-component) |
| ColorPickerAlphaSlider | Opacity slider with checkerboard pattern |
| ColorPickerAlphaSliderTrack | Alpha slider gradient track (sub-component) |
| ColorPickerAlphaSliderThumb | Alpha slider draggable thumb (sub-component) |
| ColorPickerInput | Color value text input with token badge and search |
| ColorPickerFormatToggle | HEX/RGB/HSL/OKLCH format switcher |
| ColorPickerEyeDropper | Native color sampling via the EyeDropper API |
| ColorPickerSwatches | Preset color swatches grid |
| ColorPickerSwatch | Individual color swatch button (sub-component) |
| ColorPickerGradientEditor | Gradient preview and stop editor |
| ColorPickerGradientSwatches | Preset gradient swatches grid |
| ColorPickerGradientSwatch | Individual gradient swatch button (sub-component) |
| ColorPickerContrastInfo | WCAG contrast-ratio readout with level badge and optional reference-color popover |
| ColorPickerContrastLine | SVG overlay for the color area drawing the WCAG threshold curve and failing region |
| GradientPreview | Standalone gradient preview with angle/position controls |
| GradientStops | Standalone gradient stop bar with draggable markers |
| TokenList | Searchable token dropdown list with keyboard navigation |
| ColorPickerPopover | Pre-composed popover preset with all controls (from /presets) |
| ColorPickerInline | Pre-composed inline preset with all controls (from /presets) |
| ColorPickerControls | Shared inner layout used by both presets (from /presets) |
Hooks
| Hook | Description |
|---|---|
| useColorPicker | Core color picker state management with HSVA internals and controlled/uncontrolled support |
| useGradient | Gradient editor state — type switching, stop CRUD, active stop tracking |
| useColorPickerContext | Access color picker context from any child component |
| usePointerDrag | Pointer drag interaction hook for building custom controls |
| useTokenDropdown | Shared dropdown state machine for token search, keyboard navigation, and click-outside dismissal |
| useAutoTokens | Auto-detect CSS custom property color tokens (SSR-safe, post-mount) |
Utilities
| Utility | Description |
|---|---|
| toCSS / fromCSS | Convert between ColorPickerValue and CSS strings (supports all gradient types) |
| isGradient / isSolidColor | Type guards for narrowing ColorPickerValue discriminated union |
| parseColor / formatColor | Parse and format colors between HEX, RGB, HSL, and OKLCH |
| detectFormat / isValidColor | Detect color format and validate color strings |
| toHSVA / fromHSVA | Convert between color strings and internal HSVA representation |
| getContrastColor | Get accessible text color (black or white) for a given background |
| contrastRatio / getWcagLevel | Compute WCAG 2.1 contrast ratio and classify it as AAA, AA, AA18, or Fail |
| colorLuminance / hsvLuminance / contrastFromLuminances | Lower-level luminance and contrast helpers for building custom accessibility UI |
| getEffectiveBackgroundColor | Walk the DOM to find the first non-transparent background color behind an element |
| resolveToken / findMatchingToken | Resolve token names to values and find tokens matching a color |
| getCSSColorTokens | Extract color tokens from CSS custom properties on the page |
| createGradientStop / createMeshGradientStop | Create gradient stop objects with auto-generated IDs |
| addStop / addStopWithCoordinates / removeStop / updateStop / moveStop | Gradient stop CRUD and repositioning helpers (addStopWithCoordinates is mesh-only) |
| sortStops / interpolateColorAt | Sort stops by position and interpolate colors at a given point |
| createDefaultGradient / createDefaultGradientFromColor | Create default gradient values by type, optionally from an existing color |
| clamp / getRelativePosition / angleFromPosition | Position math utilities for custom control implementations |