Color Picker
ridiculous/color-pickerFreeComponent
Ridiculously typed color picker with oklch L×C pad, hue/alpha strips, and 6-mode round-trip (oklch, oklab, hex, rgb, hsl, hwb).
Install it
npx shadcn@latest add http://ridiculous.turtlesocks.dev/r/color-picker.jsonSource
1"use client"23import { useEffect, useRef, useState } from "react"4import {5 Popover,6 PopoverContent,7 PopoverTrigger,8} from "@/components/ui/popover"9import { cn } from "@/lib/utils"10import { AlphaStrip } from "./alpha-strip"11import { MAX_RECENTS, PRESETS } from "./color-picker.constants"12import {13 formatColor,14 formatHex,15 parseColor,16 parseHex,17 pushRecent,18 resolveCssColor,19 srgbToOklch,20} from "./color-picker.helpers"21import { useControllableState } from "./color-picker.hooks"22import type {23 ColorMode,24 ColorString,25 ColorValue,26 Oklch,27} from "./color-picker.types"28import { HueStrip } from "./hue-strip"29import { LcPad } from "./lc-pad"30import { ModeButtonGroup } from "./mode-button-group"31import { type SwatchEntry, SwatchRow } from "./swatch-row"3233export interface ColorPickerProps<34 TMode extends ColorMode | undefined = undefined,35> {36 value: ColorString | (string & {})37 onChange: (value: ColorValue<TMode>) => void38 mode?: TMode39 native?: boolean40 className?: string41 "aria-label"?: string42 /**43 * Preset swatches. Each entry is a color value OR a CSS variable44 * (`"var(--color-primary)"` or bare `"--color-primary"`). `undefined` →45 * the built-in palette; `[]` → no preset row. NOTE: this project's Tailwind46 * v4 theme tokens are `--color-*`; pass the full name. A CSS-var entry must47 * resolve to an sRGB-representable color (wide-gamut P3 tokens are skipped).48 */49 presets?: ReadonlyArray<ColorString | (string & {})>50 /** Controlled recents. When provided, the component does not own this state. */51 history?: ReadonlyArray<ColorValue<TMode>>52 /** Uncontrolled initial recents. Ignored when `history` is provided. */53 defaultHistory?: ReadonlyArray<ColorValue<TMode>>54 /**55 * Fired when recents change (a color committed on popover close). Fires in56 * both modes. Passing `history` without `onHistoryChange` yields a frozen,57 * read-only recents row.58 */59 onHistoryChange?: (history: ColorValue<TMode>[]) => void60}6162export function ColorPicker<TMode extends ColorMode | undefined>({63 value,64 onChange,65 mode: modeProp,66 native = false,67 className,68 "aria-label": ariaLabel = "Pick a color",69 presets,70 history,71 defaultHistory,72 onHistoryChange,73}: ColorPickerProps<TMode>) {74 const parsedFromValue = parseColor(value)7576 // Internal canonical oklch is the source of truth for the L×C pad / sliders.77 // We do NOT derive marker position from each re-parse of `value`, because78// … truncated
What it pulls in
Other registry items
Files it writes
More from ridiculous
All 22 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| All ridiculous componentsall | ridiculous | Components | Free | no deps | |
| Anchor Position Editoranchor-position-editor | ridiculous | Components | Free | no deps · 9 files | |
| Background Editorbackground-editor | ridiculous | Components | Free | no deps · 9 files | |
| Box Shadow Editorbox-shadow-editor | ridiculous | Components | Free | no deps · 7 files | |
| Calc Editorcalc-editor | ridiculous | Components | Free | no deps · 4 files | |
| Clip Path Editorclip-path-editor | ridiculous | Components | Free | no deps · 20 files | |
| Color Functioncolor-function | ridiculous | Components | Free | no deps · 10 files | |
| Easing Pickereasing-picker | ridiculous | Components | Free | no deps · 17 files |
