Color Picker
An interactive color picker component with RGB, HSV, and hex support. Features include color panel selection, hue slider, hex input, clipboard integration, and eyedropper tool.
An interactive color picker component with RGB, HSV, and hex support. Features include color panel selection, hue slider, hex input, clipboard integration, and eyedropper tool.
npm install react-colorful
1"use client";23import { Button } from "@/components/website/ui/button";4import { Input } from "@/components/website/ui/input";5import { Label } from "@/components/website/ui/label";6import {7Popover,8PopoverContent,9PopoverTrigger,10} from "@/components/website/ui/popover";11import { cn } from "@/lib/utils";12import { Copy, Pipette } from "lucide-react";13import { HexColorPicker } from "react-colorful";14import { toast } from "sonner";1516interface ColorPickerProps {17color: string18onChange: (color: string) => void19label: string20isEyeDroppper?:boolean21className?:string22}2324export function ColorPicker({25color,26onChange,27label,28isEyeDroppper = false,29className,30}: ColorPickerProps) {31function copyToClipboard() {32navigator.clipboard.writeText(color);33toast("Copied!", {34description: `${color} copied to clipboard`,35duration: 2000,36});37}3839async function useEyeDropper() {40if (!("EyeDropper" in window)) {41toast.error("Not supported", {42description: "Eyedropper is not supported in your browser",43duration: 3000,44});45return;46}4748try {49// @ts-expect-error - EyeDropper is not in the TypeScript DOM types yet50const eyeDropper = new window.EyeDropper();51const result = await eyeDropper.open();52onChange(result.sRGBHex);53} catch (e) {54console.error("Error using eyedropper", e);55}56}5758return (59<div className={cn("flex items-center gap-2",className)}>60<Label className="w-24">{label}</Label>61<Popover>62<PopoverTrigger asChild>63<Button64variant="outline"65className="h-8 w-12 border-2 p-0"66style={{ backgroundColor: color }}67>68<span className="sr-only">Pick a color</span>69</Button>70</PopoverTrigger>71<PopoverContent className="w-full p-3 bg-primary-foreground">72<HexColorPicker73color={color}74onChange={onChange}75className="!w-full"76/>77<div className="mt-2 flex w-full gap-2">78<Input79value={color}80onChange={(e) => onChange(e.target.value)}81className="h-10 w-full"82/>83<Button84variant="outline"85size="icon"86onClick={copyToClipboard}87className="h-10 w-12 shrink border-gray-300 bg-gray-100 text-gray-900 hover:bg-gray-200"88style={{ borderRadius: "6px" }}89>90<Copy className="h-4 w-4" />91<span className="sr-only">Copy color</span>92</Button>93</div>9495{isEyeDroppper && (96<div className="mt-2 flex gap-2">97<Button98variant="outline"99size="icon"100onClick={useEyeDropper}101className="h-10 w-10 border-gray-300 bg-gray-100 text-gray-900 hover:bg-gray-200"102style={{ borderRadius: "6px" }}103>104<Pipette className="h-4 w-4" />105<span className="sr-only">Pick color</span>106</Button>107108<div109className="h-10 flex-1"110style={{ backgroundColor: color, borderRadius: "6px" }}111/>112</div>113)}114</PopoverContent>115</Popover>116</div>117);118}
Props | Type | Default | Description |
---|---|---|---|
color | string | — | The current color value. |
onChange | (color: string) => void | — | Callback fired when the color is changed. |
label | string | — | Label displayed above the color picker. |
isEyeDroppper | boolean | false | Whether to enable the eyedropper feature. |
className | string | false | Whether to enable the eyedropper feature. |