ui
ui copied to clipboard
is there a color-picker component ui ?
I have checked all the documents and found no similar components, I think it is strange, this is a general component,
is there something I missed? or there is other solution ?
Not a ready solution but you could use, for example, either of these two inside a Popover: https://github.com/omgovich/react-colorful https://github.com/casesandberg/react-color
Maybe someone could move this issue (which it isn't) to discussions.
I made a color + gradient + image picker.
- Docs: https://gradient.page/picker
- Github: https://github.com/illyism/gradient-picker
@Illyism very nice example! Following the same logic, it should be rather easy to place this https://github.com/omgovich/react-colorful inside the popover.
+1
npm install colord react-colorful
color-pick.tsx
code:
// https://codesandbox.io/s/6fp23?file=/src/CustomPicker.js
import { colord, extend } from "colord"
import namesPlugin from "colord/plugins/names"
import React, { useEffect, useMemo, useRef } from "react"
import { RgbaStringColorPicker } from "react-colorful"
extend([namesPlugin])
type ColorPickerProps = {
color: string
onChange: (color: string) => void
}
const CustomPicker = ({ color, ...rest }) => {
const rgbaString = useMemo(() => {
return color?.startsWith("rgba") ? color : colord(color).toRgbString()
}, [color])
return <RgbaStringColorPicker color={rgbaString} {...rest} />
}
export const ColorPicker: React.FC<ColorPickerProps> = (props) => {
const [visible, setVisible] = React.useState(false)
const [color, setColor] = React.useState(props.color)
const ref = useRef<HTMLDivElement>(null)
useEffect(() => {
setColor(props.color)
}, [props.color])
useEffect(() => {
if (!ref.current) {
return
}
const handleClick = (e: MouseEvent) => {
if (!ref.current?.contains(e.target as Node)) {
setVisible(false)
}
}
document.addEventListener("click", handleClick)
return () => {
document.removeEventListener("click", handleClick)
}
}, [])
return (
<div
ref={ref}
className="relative w-8 h-8 rounded-sm cursor-pointer border"
style={{ backgroundColor: color }}
onClick={() => {
setVisible(true)
}}>
{visible && (
<div className="absolute top-0 right-[-210px]">
<CustomPicker
color={props.color}
onChange={(color) => {
setColor(color)
props.onChange && props.onChange(color)
}}
/>
</div>
)}
</div>
)
}
How to use:
<ColorPicker
color="rgba(70,80,90,0.5)"
onChange={(color) => {
// todo
}}
/>;
Here is a very simple one. Using the Popover, Input & Button component. Changed the styling a bit to my needs but are simple to change.
import React, { useEffect } from "react"
import { Popover, PopoverContent, PopoverTrigger } from "./popover"
import { Button } from "./button"
import { Input } from "./input"
type ColorPickerProps = {
value: string
onChange: (color: string) => void
items?: Item[]
}
type Item = {
value: string;
label: string;
}
export const ColorPicker: React.FC<ColorPickerProps> = ({value, onChange, items}) => {
const [color, setColor] = React.useState(value)
useEffect(() => {
setColor(value)
}, [value])
return (
<Popover>
<PopoverTrigger asChild>
<Button className="bg-transparent hover:bg-white/10">
<div style={{ backgroundColor: color }} className="w-5 h-5 rounded-md mr-2 border border-white/10"></div>
<p>{color}</p>
</Button>
</PopoverTrigger>
<PopoverContent className="space-y-4">
{items &&
<div className="flex flex-wrap gap-2">
{items.map((item,index)=>(
<button onClick={()=>{ onChange&&onChange(item.value); setColor(item.value) }} key={index} className="w-5 h-5 rounded-md aspect-square border" style={{backgroundColor:item.value}}></button>
))}
</div>
}
<Input value={color} onChange={({currentTarget})=>{ onChange&&onChange(currentTarget.value); setColor(currentTarget.value) }}/>
</PopoverContent>
</Popover>
)
}
Example on how to use
<ColorPicker value={color} onChange={(color)=>{changeColor(color)}} items={[{value:'#e11d48', label:''}, {value:'#db2777', label:''}, {value:'#c026d3', label:''}, {value:'#9333ea', label:''}, {value:'#4f46e5', label:''}, {value:'#0284c7', label:''}, {value:'#0d9488', label:''}, {value:'#059669', label:''}, {value:'#16a34a', label:''}, {value:'#ca8a04', label:''}, {value:'#ea580c', label:''}, {value:'#dc2626', label:''}, {value:'#000000', label:''}, {value:'#ffffff', label:''}]}/>