New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

chromakit-react

Package Overview
Dependencies
Maintainers
1
Versions
17
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

chromakit-react

A modern React color picker library with support for OKLCH, OKLAB, and traditional color spaces

latest
Source
npmnpm
Version
0.1.16
Version published
Maintainers
1
Created
Source

ChromaKit

The Modern React Color Picker with Perceptually Uniform Colors

Build better design systems with OKLCH color space support

npm version npm downloads bundle size license TypeScript

Live DemoDocumentationMigration Guide

npm install chromakit-react

See it in action →


ChromaKit - Modern React color picker with OKLCH support

Table of Contents

Why Developers Choose ChromaKit

The only React color picker built for modern design systems. While other pickers struggle with consistent color scales and muddy gradients, ChromaKit uses perceptually uniform color spaces (OKLCH, OKLAB) to deliver what designers expect and users see.

// Get started in 30 seconds
import { ColorPicker } from 'chromakit-react';
import 'chromakit-react/chromakit.css';

<ColorPicker onChange={(color) => console.log(color.oklch)} />;

Perfect For

  • Design System Engineers - Generate consistent tonal scales with predictable lightness
  • Accessibility Teams - Built-in WCAG AA/AAA contrast checking
  • App Developers - Zero dependencies, 10KB bundle, works everywhere
  • UI Libraries - Composable primitives, full TypeScript support

What Makes ChromaKit Different

Perceptually Uniform Colors

The Problem: Traditional RGB/HSL create inconsistent color scales. A 10% lightness change in blue looks different than in yellow. Your carefully crafted design system falls apart.

ChromaKit's Solution: OKLCH color space ensures equal numerical changes produce equal visual differences. Generate accessible color palettes that actually look evenly spaced.

// Generate a perfectly uniform color scale
const scale = Array.from({ length: 9 }, (_, i) => {
  const lightness = 0.2 + i * 0.1; // 20% to 100%
  return `oklch(${lightness} 0.15 250)`; // Consistently spaced blues
});

Composable Architecture

Unlike monolithic pickers, ChromaKit gives you building blocks:

import {
  ColorArea,
  HueSlider,
  AlphaSlider,
  useColorState,
} from 'chromakit-react';

// Build your perfect picker layout
function CustomPicker() {
  const { hsva, colorValue, updateColor } = useColorState('#6366F1');
  return (
    <>
      <ColorArea hsva={hsva} onChange={updateColor} />
      <HueSlider hsva={hsva} onChange={updateColor} />
      <AlphaSlider hsva={hsva} onChange={updateColor} />
    </>
  );
}

Built for Performance

  • 10KB gzipped - Competitive with alternatives, but includes OKLCH + composability
  • Zero dependencies - No supply chain risk, no version conflicts
  • Tree-shakeable - Import only what you use
  • 60fps interactions - Smooth dragging on all devices

Accessibility Baked In

  • WCAG AA compliant - Full keyboard navigation, proper ARIA labels
  • Contrast checker included - getContrastRatio(), meetsContrastRatio()
  • Screen reader tested - Works with NVDA, JAWS, VoiceOver
  • Touch-friendly - 44px minimum touch targets

TypeScript Excellence

Every color format, every component prop, every utility function - fully typed:

import type { ColorValue, OKLCHColor, RGBColor } from 'chromakit-react';

const handleChange = (value: ColorValue) => {
  value.oklch; // { l: number, c: number, h: number }
  value.rgb; // { r: number, g: number, b: number }
  value.hex; // string
};

Comparison

FeatureChromaKitreact-colorfulreact-color
Bundle Size~10KB~3KB~28KB
OKLCH/OKLAB
ComposableLimited
TypeScript✅ Native⚠️ @types
Dark Mode✅ Built-inManualManual
Dependencies00Many

Choose ChromaKit for: Design systems, OKLCH support, accessibility features, composability
Choose react-colorful for: Minimal bundle size (<5KB), traditional RGB/HSL only

Migration Guide available for switching from react-colorful or react-color.

Quick Start

Controlled Component (recommended)

import { useState } from 'react';
import { ColorPicker } from 'chromakit-react';
import 'chromakit-react/chromakit.css';

function App() {
  const [color, setColor] = useState('#6366F1');

  return (
    <ColorPicker
      value={color}
      onChange={(colorValue) => setColor(colorValue.hex)}
    />
  );
}

That's it! You now have a fully-featured color picker with OKLCH support, eyedropper, color history, and more.

Why OKLCH?

OKLCH is a perceptually uniform color space - equal numerical changes produce equal visual differences.

Key Benefits:

  • Predictable Lightness: oklch(0.5 ...) appears equally bright regardless of hue, unlike HSL
  • Better Gradients: Smooth transitions without muddy middle tones
  • Design Systems: Generate consistent tonal scales with uniform visual weight
  • Wide Gamut: Access more vibrant colors on modern displays

Parameters:

  • L (Lightness): 0 (black) to 1 (white)
  • C (Chroma): 0 (grayscale) to ~0.4 (vibrant)
  • H (Hue): 0-360° around the color wheel
// HSL: Same lightness value, different perceived brightness
hsl(240, 100%, 50%) // Blue - looks dark
hsl(60, 100%, 50%)  // Yellow - looks bright

// OKLCH: Same lightness = same perceived brightness
oklch(0.5 0.2 240)  // Blue at 50% brightness
oklch(0.5 0.2 60)   // Yellow at 50% brightness

Learn more about OKLCH →

Framework Setup

Next.js App Router

'use client';
import { ColorPicker } from 'chromakit-react';
import 'chromakit-react/chromakit.css';

export function MyColorPicker() {
  const [color, setColor] = useState('#6366F1');
  return <ColorPicker value={color} onChange={(c) => setColor(c.hex)} />;
}

Next.js Pages Router (SSR)

import dynamic from 'next/dynamic';

const ColorPicker = dynamic(
  () => import('chromakit-react').then((mod) => mod.ColorPicker),
  { ssr: false }
);

Vite / CRA

import { ColorPicker } from 'chromakit-react';
import 'chromakit-react/chromakit.css';
// Works out of the box

API Reference

ColorPicker

Full-featured color picker component.

interface ColorPickerProps {
  value?: string;
  defaultValue?: string;
  onChange?: (color: ColorValue) => void;
  onChangeComplete?: (color: ColorValue) => void;
  formats?: ColorFormat[];
  showAlpha?: boolean;
  showInputs?: boolean;
  showPreview?: boolean;
  showCopyButton?: boolean;
  showEyeDropper?: boolean;
  showPresets?: boolean;
  presets?: string[];
  presetGroups?: PresetGroup[] | Record<string, string[]>;
  enableHistory?: boolean;
  width?: number;
  height?: number;
  className?: string;
}

Props:

PropTypeDefaultDescription
valuestring-Controlled color value (any supported format)
defaultValuestring'#6366F1'Initial color for uncontrolled mode
onChange(color: ColorValue) => void-Fires during color changes (real-time)
onChangeComplete(color: ColorValue) => void-Fires when user completes a change (mouse up, blur)
formatsColorFormat[]['hex', 'rgb', 'hsl', 'oklch']Available color format options
showAlphabooleantrueEnable alpha channel controlha channel control
showInputsbooleantrueShow color input fields
showPreviewbooleantrueShow color preview swatch
showCopyButtonbooleantrueShow copy button (enables Cmd/Ctrl+C)
showEyeDropperbooleantrueShow eyedropper button (if browser supports)
showPresetsbooleantrueShow preset colors section
presetsstring[]Built-in defaultsCustom preset colors array
presetGroupsPresetGroup[] or Record<string, string[]>Built-in groupsPreset color groups with dropdown
enableHistorybooleantrueStore recent colors in localStorage
widthnumberautoCustom picker width in pixels
heightnumber100Color area height in pixels
classNamestring-Additional CSS classes

ColorValue Object:

The onChange and onChangeComplete callbacks receive a ColorValue object:

interface ColorValue {
  hex: string; // "#ff6b6b"
  hex8: string; // "#ff6b6bff"
  rgb: RGBColor; // { r: 255, g: 107, b: 107 }
  rgba: RGBAColor; // { r: 255, g: 107, b: 107, a: 1 }
  hsl: HSLColor; // { h: 0, s: 100, l: 71 }
  hsla: HSLAColor; // { h: 0, s: 100, l: 71, a: 1 }
  hsv: HSVColor; // { h: 0, s: 58, v: 100 }
  hsva: HSVAColor; // { h: 0, s: 58, v: 100, a: 1 }
  oklch: OKLCHColor; // { l: 0.71, c: 0.19, h: 25 }
  oklcha: OKLCHAColor; // { l: 0.71, c: 0.19, h: 25, a: 1 }
  oklab: OKLABColor; // { l: 0.71, a: 0.17, b: 0.08 }
  oklaba: OKLABAColor; // { l: 0.71, a: 0.17, b: 0.08, alpha: 1 }
}

Composable Components

Build custom pickers using primitive components for complete layout control:

import {
  ColorArea,
  HueSlider,
  AlphaSlider,
  ColorPreview,
  ColorInputs,
  useColorState,
} from 'chromakit-react';

function CustomPicker() {
  const { hsva, colorValue, updateColor } = useColorState('#ff0000');

  return (
    <div className="custom-picker">
      <ColorArea hsva={hsva} onChange={updateColor} width={200} height={150} />
      <HueSlider hsva={hsva} onChange={updateColor} />
      <AlphaSlider hsva={hsva} onChange={updateColor} />
      <ColorPreview colorValue={colorValue} size="lg" />
      <ColorInputs
        colorValue={colorValue}
        onChange={(hex) => updateColor(parseColor(hex))}
        format="hex"
      />
    </div>
  );
}

Component Props:

ColorArea - 2D saturation/lightness picker
interface ColorAreaProps {
  hsva: HSVAColor;
  onChange: (hsva: HSVAColor) => void;
  onStart?: () => void;
  onEnd?: () => void;
  width?: number; // Default: 256
  height?: number; // Default: 200
  className?: string;
}
HueSlider - Hue selection slider
interface HueSliderProps {
  hsva: HSVAColor;
  onChange: (hsva: HSVAColor) => void;
  onStart?: () => void;
  onEnd?: () => void;
  vertical?: boolean; // Default: false
  className?: string;
}
AlphaSlider - Alpha/transparency slider
interface AlphaSliderProps {
  hsva: HSVAColor;
  onChange: (hsva: HSVAColor) => void;
  onStart?: () => void;
  onEnd?: () => void;
  vertical?: boolean; // Default: false
  className?: string;
}
ColorPreview - Color swatch with comparison
interface ColorPreviewProps {
  colorValue: ColorValue;
  showComparison?: boolean; // Show before/after
  originalColor?: string; // Original color for comparison
  size?: 'sm' | 'md' | 'lg'; // Default: 'md'
  className?: string;
}
ColorInputs - Format-switchable input fields
interface ColorInputsProps {
  colorValue: ColorValue;
  onChange: (hexColor: string) => void;
  format: ColorFormat;
  onFormatChange?: (format: ColorFormat) => void;
  showAlpha?: boolean;
  availableFormats?: ColorFormat[];
  className?: string;
}
ColorSwatch - Individual color button
interface ColorSwatchProps {
  color: string;
  onClick?: () => void;
  active?: boolean;
  size?: 'sm' | 'md' | 'lg';
  className?: string;
}
RecentColors - Color history display
interface RecentColorsProps {
  onColorSelect?: (color: string) => void;
  maxColors?: number; // Default: 10
  className?: string;
}

Hooks

useColorState - Main color state management hook

function useColorState(initialColor?: string) {
  return {
    hsva: HSVAColor;           // Internal HSVA representation
    colorValue: ColorValue;     // All format conversions
    updateColor: (hsva: HSVAColor) => void;
    setColorFromString: (color: string) => void;
  };
}

useDrag - Drag interaction handler (for custom components)

function useDrag(
  ref: RefObject<HTMLElement>,
  onDrag: (x: number, y: number) => void,
  onStart?: () => void,
  onEnd?: () => void
): void;

Examples

Basic Usage

Simple controlled picker

const [color, setColor] = useState('#6366F1');

<ColorPicker
  value={color}
  onChange={(colorValue) => setColor(colorValue.hex)}
/>;

Preset Colors

Custom preset colors

<ColorPicker
  value={color}
  onChange={(colorValue) => setColor(colorValue.hex)}
  presets={['#FF6B6B', '#4ECDC4', '#45B7D1', '#FFA07A', '#98D8C8', '#F7DC6F']}
/>

Preset groups with dropdown (New in v0.1.10)

const presetGroups = [
  {
    name: 'Material',
    colors: ['#F44336', '#E91E63', '#9C27B0', '#673AB7', '#3F51B5'],
  },
  {
    name: 'Tailwind',
    colors: ['#EF4444', '#F97316', '#EAB308', '#22C55E', '#10B981'],
  },
];

<ColorPicker
  value={color}
  onChange={(colorValue) => setColor(colorValue.hex)}
  presetGroups={presetGroups}
/>;

Or use object format:

const presetGroups = {
  Material: ['#F44336', '#E91E63', '#9C27B0', '#673AB7', '#3F51B5'],
  Tailwind: ['#EF4444', '#F97316', '#EAB308', '#22C55E', '#10B981'],
};

<ColorPicker
  value={color}
  onChange={(colorValue) => setColor(colorValue.hex)}
  presetGroups={presetGroups}
/>;

Format Control

Limit available formats

<ColorPicker
  value={color}
  onChange={(colorValue) => setColor(colorValue.hex)}
  formats={['oklch', 'hex', 'rgb']}
/>

Advanced Features

Track color changes completion

<ColorPicker
  value={color}
  onChange={(colorValue) => {
    // Fires during dragging (real-time updates)
    setColor(colorValue.hex);
  }}
  onChangeComplete={(colorValue) => {
    // Fires when user finishes selecting (mouse up, blur)
    // Perfect for API calls or expensive operations
    saveColorToDatabase(colorValue.hex);
  }}
/>

Color history with localStorage

<ColorPicker
  value={color}
  onChange={(colorValue) => setColor(colorValue.hex)}
  enableHistory={true} // Automatically saves recent colors
/>

Access all color formats

<ColorPicker
  value={color}
  onChange={(colorValue) => {
    console.log(colorValue.hex); // "#ff6b6b"
    console.log(colorValue.rgb); // { r: 255, g: 107, b: 107 }
    console.log(colorValue.oklch); // { l: 0.71, c: 0.19, h: 25 }
    setColor(colorValue.hex);
  }}
/>

Eyedropper & Copy Features

Built-in eyedropper and copy buttons

<ColorPicker
  value={color}
  onChange={(colorValue) => setColor(colorValue.hex)}
  showEyeDropper={true} // Shows eyedropper button (if browser supports)
  showCopyButton={true} // Shows copy button + enables Cmd/Ctrl+C
/>

Note: The EyeDropper API requires a secure context (HTTPS) and is currently supported in Chrome/Edge 95+, not yet in Firefox or Safari.

Form Integration

React Hook Form

import { Controller, useForm } from 'react-hook-form';
import { ColorPicker } from 'chromakit-react';

function MyForm() {
  const { control, handleSubmit } = useForm({
    defaultValues: { brandColor: '#6366F1' }
  });

  return (
    <form onSubmit={handleSubmit(data => console.log(data))}>
      <Controller
        name="brandColor"
        control={control}
        render={({ field }) => (
          <ColorPicker
            value={field.value}
            onChange={(c) => field.onChange(c.hex)}
          />
        )}
      />
    </form>
  );
}

Formik

import { useFormik } from 'formik';
import { ColorPicker } from 'chromakit-react';

function MyForm() {
  const formik = useFormik({
    initialValues: { brandColor: '#6366F1' },
    onSubmit: values => console.log(values)
  });

  return (
    <form onSubmit={formik.handleSubmit}>
      <ColorPicker
        value={formik.values.brandColor}
        onChange={(c) => formik.setFieldValue('brandColor', c.hex)}
      />
    </form>
  );
}

Color Utilities

Conversion Functions

Convert between any color format:

import {
  hexToRgb,
  rgbToHex,
  rgbToHsl,
  hslToRgb,
  rgbToOklch,
  oklchToRgb,
  parseColor,
  colorValueToString,
} from 'chromakit-react';

// Parse any format
const parsed = parseColor('#ff6b6b');
// Returns: { r: 255, g: 107, b: 107, a: 1 }

// Convert between formats
const rgb = hexToRgb('#ff0000'); // { r: 255, g: 0, b: 0 }
const hex = rgbToHex(rgb); // '#ff0000'
const hsl = rgbToHsl(rgb); // { h: 0, s: 100, l: 50 }
const oklch = rgbToOklch(rgb); // { l: 0.63, c: 0.26, h: 29 }

// Format color value to string
const color = { r: 255, g: 107, b: 107, a: 1 };
const hexString = colorValueToString(color, 'hex'); // "#ff6b6b"
const rgbString = colorValueToString(color, 'rgb'); // "rgb(255, 107, 107)"
const oklchString = colorValueToString(color, 'oklch'); // "oklch(0.71 0.19 25)"

Available conversion functions:

  • hexToRgba(hex) - Parse hex to RGBA
  • parseColor(color) - Parse any format to RGBA
  • rgbToHex(rgb) - RGB to 6-digit hex
  • rgbaToHex8(rgba) - RGBA to 8-digit hex
  • rgbToHsl(rgb) / hslToRgb(hsl)
  • rgbaToHsla(rgba) / hslaToRgba(hsla)
  • rgbToHsv(rgb) / hsvToRgb(hsv)
  • rgbaToHsva(rgba) / hsvaToRgba(hsva)
  • rgbToOklab(rgb) / oklabToRgb(oklab)
  • rgbaToOklaba(rgba) / oklabaToRgba(oklaba)
  • rgbToOklch(rgb) / oklchToRgb(oklch)
  • rgbaToOklcha(rgba) / oklchaToRgba(oklcha)
  • oklabToOklch(oklab) / oklchToOklab(oklch)
  • rgbaToColorValue(rgba) - Convert to all formats
  • colorValueToString(colorValue, format) - Format to string

Color Formats

ChromaKit supports the following color formats:

FormatExampleDescription
HEX#ff0000Hexadecimal RGB
HEX8#ff0000ffHex with alpha
RGBrgb(255, 0, 0)Red, Green, Blue
RGBArgba(255, 0, 0, 1)RGB with alpha
HSLhsl(0, 100%, 50%)Hue, Saturation, Lightness
HSLAhsla(0, 100%, 50%, 1)HSL with alpha
HSVhsv(0, 100%, 100%)Hue, Saturation, Value
HSVAhsva(0, 100%, 100%, 1)HSV with alpha
OKLCHoklch(0.63 0.26 29)Perceptually uniform cylindrical
OKLCHAoklch(0.63 0.26 29 / 1)OKLCH with alpha
OKLABoklab(0.63 0.22 0.13)Perceptually uniform Cartesian

Theming & Customization

Override CSS variables for custom themes:

.my-custom-picker {
  --ck-primary: #9333ea;
  --ck-bg: #0a0a0b;
  --ck-text: #ffffff;
  --ck-radius: 8px;
}
<ColorPicker className="my-custom-picker" />

See source CSS for all available variables.

Browser Support

ChromaKit works in all modern browsers:

  • Chrome/Edge: 88+
  • Firefox: 87+
  • Safari: 15+
  • Node.js: 20+ (for SSR/build tools)

Feature Support

FeatureBrowser SupportFallback
Color PickerAll modern browsers-
OKLCH/OKLAB calculationsAll modern browsers-
CSS oklch() syntaxChrome 111+, Firefox 113+, Safari 15.4+Use hex/rgb output
EyeDropper APIChrome/Edge 95+Button hidden automatically
Clipboard APIAll modern browsers (HTTPS required)Manual copy

For CSS OKLCH color space support, see Can I Use: OKLCH.

TypeScript

ChromaKit is written in TypeScript and provides complete type definitions for all exports.

Type Exports

import type {
  // Color format types
  RGBColor,
  RGBAColor,
  HSLColor,
  HSLAColor,
  HSVColor,
  HSVAColor,
  OKLCHColor,
  OKLCHAColor,
  OKLABColor,
  OKLABAColor,

  // Utility types
  ColorFormat,
  ColorValue,
  AnyColor,

  // Component props
  ColorPickerProps,
  ColorAreaProps,
  HueSliderProps,
  AlphaSliderProps,

  // Preset types
  PresetGroup,
  PresetGroupsInput,
} from 'chromakit-react';

Type-Safe Color Conversions

import {
  rgbToHsl,
  hslToRgb,
  type RGBColor,
  type HSLColor,
} from 'chromakit-react';

const rgb: RGBColor = { r: 255, g: 107, b: 107 };
const hsl: HSLColor = rgbToHsl(rgb);
// Type: { h: number; s: number; l: number }

const backToRgb: RGBColor = hslToRgb(hsl);
// Fully typed with autocomplete

Troubleshooting

Common Issues

Issue: Styles not loading

Make sure to import the CSS file:

import 'chromakit-react/chromakit.css';

Or if using automatic imports, ensure your bundler processes CSS side effects.

Issue: Eyedropper not showing

The EyeDropper API requires:

  • Secure context (HTTPS in production, localhost in development)
  • Browser support (Chrome/Edge 95+)
  • User permission

Check browser support:

if ('EyeDropper' in window) {
  // Eyedropper available
}

Issue: TypeScript errors with color formats

Ensure you're using the correct types:

import type { ColorValue } from 'chromakit-react';

const handleChange = (colorValue: ColorValue) => {
  // colorValue has all format properties
  console.log(colorValue.hex);
  console.log(colorValue.oklch);
};

Issue: Next.js "window is not defined" error

For server-side rendering, use dynamic imports:

import dynamic from 'next/dynamic';

const ColorPicker = dynamic(
  () => import('chromakit-react').then((mod) => mod.ColorPicker),
  { ssr: false }
);

Issue: Color history not persisting

History uses localStorage with key chromakit-color-history. Ensure:

  • localStorage is available (not in incognito/private mode)
  • enableHistory prop is true (default)
  • Browser has storage permissions

Clear history manually:

import { clearColorHistory } from 'chromakit-react';
clearColorHistory();

**I## Resources

Support

License

MIT © Garrett Siegel

Credits

Built with:

chromakit.site

Star on GitHubTry Live DemoReport Bug Color science based on:

Design inspired by:

```

Keywords

react

FAQs

Package last updated on 30 Jan 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts