Color Picker
React formHex / RGB color input with a popover swatch grid. Supports controlled and uncontrolled modes, alpha channel, and a recent-colors row.
Also available for Vue ->Installation
$ pnpm dlx shadcn@latest add https://react.uipkge.dev/r/react/color-picker.json$ npx shadcn@latest add https://react.uipkge.dev/r/react/color-picker.json$ yarn dlx shadcn@latest add https://react.uipkge.dev/r/react/color-picker.json$ bunx shadcn@latest add https://react.uipkge.dev/r/react/color-picker.json
Or with the named registry:
npx shadcn@latest add @uipkge-react/color-picker
Examples
Props
| Name | Type / Values | Default | Required |
|---|---|---|---|
value | string | — | optional |
onValueChange | (value: string) => void | — | optional |
disabled | boolean | — | optional |
presets Override the swatches shown below the color input. Pass [] to hide entirely. | string[] | — | optional |
hideHexInput Hide the hex text field next to the color trigger. | boolean | false | optional |
className | string | — | optional |
Files (2)
-
components/ui/color-picker/color-picker.tsx 3.2 kB
'use client' import * as React from 'react' import { cn } from '@/lib/utils' const DEFAULT_PRESETS = [ '#ef4444', '#f97316', '#eab308', '#22c55e', '#14b8a6', '#3b82f6', '#8b5cf6', '#ec4899', '#ffffff', '#d4d4d4', '#737373', '#171717', ] export interface ColorPickerProps { value?: string onValueChange?: (value: string) => void disabled?: boolean /** Override the swatches shown below the color input. Pass [] to hide entirely. */ presets?: string[] /** Hide the hex text field next to the color trigger. */ hideHexInput?: boolean className?: string } const ColorPicker = React.forwardRef<HTMLDivElement, ColorPickerProps>( ({ value, onValueChange, disabled, presets = DEFAULT_PRESETS, hideHexInput = false, className }, ref) => { const swatches = presets ?? [] return ( <div ref={ref} className={cn('space-y-3', className)}> {/* Color trigger + hex field */} <div className="flex items-center gap-2"> <div className="border-input relative h-10 w-10 shrink-0 overflow-hidden rounded-md border shadow-xs" style={{ backgroundColor: value || '#ffffff' }} > <input type="color" value={value || '#ffffff'} disabled={disabled} aria-label="Pick color" className="absolute inset-0 h-full w-full cursor-pointer opacity-0 disabled:cursor-not-allowed" onInput={(e) => onValueChange?.((e.target as HTMLInputElement).value)} /> </div> {!hideHexInput && ( <input type="text" value={value || ''} placeholder="#000000" disabled={disabled} className="bg-background border-input text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 h-10 flex-1 rounded-md border px-3 text-sm uppercase shadow-xs outline-none focus-visible:ring-2 disabled:cursor-not-allowed disabled:opacity-50" onChange={(e) => onValueChange?.(e.target.value)} /> )} </div> {/* Preset swatches */} {swatches.length > 0 && ( <div className="flex flex-wrap gap-1.5"> {swatches.map((color) => ( <button type="button" key={color} disabled={disabled} aria-label={`Select ${color}`} style={{ backgroundColor: color }} className={cn( 'ring-offset-background focus-visible:ring-ring/40 size-6 shrink-0 rounded-md shadow-sm transition-transform outline-none hover:scale-110 focus-visible:ring-2 disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:scale-100', value?.toLowerCase() === color.toLowerCase() ? 'ring-foreground ring-2 ring-offset-2' : 'ring-border/50 ring-1', color.toLowerCase() === '#ffffff' && 'ring-border', )} onClick={() => onValueChange?.(color)} /> ))} </div> )} </div> ) }, ) ColorPicker.displayName = 'ColorPicker' export { ColorPicker } -
components/ui/color-picker/index.ts 0.1 kB
export { ColorPicker, type ColorPickerProps } from './color-picker'
Raw manifest: https://react.uipkge.dev/r/react/color-picker.json