@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-picker

Playground

Configure the color picker interactively and copy the generated code.

Preview

Options

Variant

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%), #e7fff5

Generated 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

ComponentDescription
ColorPickerRoot provider and context. Accepts tokens and autoTokens props.
ColorPickerProviderHeadless provider without Radix Popover (for custom layouts)
ColorPickerTriggerPopover trigger button with color swatch
ColorPickerInputTriggerInput-style trigger with inline editing and token badge
ColorPickerContentPopover content wrapper with portal support
ColorPickerModeSelectorSolid/gradient mode radio group toggle
ColorPickerModeSelectorItemIndividual mode option (solid, linear, radial, conic, mesh)
ColorPickerAreaSaturation/brightness 2D area
ColorPickerAreaGradientArea background gradient layer (sub-component)
ColorPickerAreaThumbArea draggable thumb (sub-component)
ColorPickerHueSliderHue selection slider
ColorPickerHueSliderTrackHue slider rainbow track (sub-component)
ColorPickerHueSliderThumbHue slider draggable thumb (sub-component)
ColorPickerAlphaSliderOpacity slider with checkerboard pattern
ColorPickerAlphaSliderTrackAlpha slider gradient track (sub-component)
ColorPickerAlphaSliderThumbAlpha slider draggable thumb (sub-component)
ColorPickerInputColor value text input with token badge and search
ColorPickerFormatToggleHEX/RGB/HSL/OKLCH format switcher
ColorPickerEyeDropperNative color sampling via the EyeDropper API
ColorPickerSwatchesPreset color swatches grid
ColorPickerSwatchIndividual color swatch button (sub-component)
ColorPickerGradientEditorGradient preview and stop editor
ColorPickerGradientSwatchesPreset gradient swatches grid
ColorPickerGradientSwatchIndividual gradient swatch button (sub-component)
ColorPickerContrastInfoWCAG contrast-ratio readout with level badge and optional reference-color popover
ColorPickerContrastLineSVG overlay for the color area drawing the WCAG threshold curve and failing region
GradientPreviewStandalone gradient preview with angle/position controls
GradientStopsStandalone gradient stop bar with draggable markers
TokenListSearchable token dropdown list with keyboard navigation
ColorPickerPopoverPre-composed popover preset with all controls (from /presets)
ColorPickerInlinePre-composed inline preset with all controls (from /presets)
ColorPickerControlsShared inner layout used by both presets (from /presets)

Hooks

HookDescription
useColorPickerCore color picker state management with HSVA internals and controlled/uncontrolled support
useGradientGradient editor state — type switching, stop CRUD, active stop tracking
useColorPickerContextAccess color picker context from any child component
usePointerDragPointer drag interaction hook for building custom controls
useTokenDropdownShared dropdown state machine for token search, keyboard navigation, and click-outside dismissal
useAutoTokensAuto-detect CSS custom property color tokens (SSR-safe, post-mount)

Utilities

UtilityDescription
toCSS / fromCSSConvert between ColorPickerValue and CSS strings (supports all gradient types)
isGradient / isSolidColorType guards for narrowing ColorPickerValue discriminated union
parseColor / formatColorParse and format colors between HEX, RGB, HSL, and OKLCH
detectFormat / isValidColorDetect color format and validate color strings
toHSVA / fromHSVAConvert between color strings and internal HSVA representation
getContrastColorGet accessible text color (black or white) for a given background
contrastRatio / getWcagLevelCompute WCAG 2.1 contrast ratio and classify it as AAA, AA, AA18, or Fail
colorLuminance / hsvLuminance / contrastFromLuminancesLower-level luminance and contrast helpers for building custom accessibility UI
getEffectiveBackgroundColorWalk the DOM to find the first non-transparent background color behind an element
resolveToken / findMatchingTokenResolve token names to values and find tokens matching a color
getCSSColorTokensExtract color tokens from CSS custom properties on the page
createGradientStop / createMeshGradientStopCreate gradient stop objects with auto-generated IDs
addStop / addStopWithCoordinates / removeStop / updateStop / moveStopGradient stop CRUD and repositioning helpers (addStopWithCoordinates is mesh-only)
sortStops / interpolateColorAtSort stops by position and interpolate colors at a given point
createDefaultGradient / createDefaultGradientFromColorCreate default gradient values by type, optionally from an existing color
clamp / getRelativePosition / angleFromPositionPosition math utilities for custom control implementations