ui icon indicating copy to clipboard operation
ui copied to clipboard

is there a color-picker component ui ?

Open joeylin opened this issue 1 year ago • 7 comments

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 ? image

joeylin avatar Jul 25 '23 08:07 joeylin

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

ttsirkia avatar Jul 26 '23 07:07 ttsirkia

Maybe someone could move this issue (which it isn't) to discussions.

ttsirkia avatar Jul 26 '23 07:07 ttsirkia

image

I made a color + gradient + image picker.

  • Docs: https://gradient.page/picker
  • Github: https://github.com/illyism/gradient-picker

Illyism avatar Aug 06 '23 06:08 Illyism

@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.

ttsirkia avatar Aug 06 '23 20:08 ttsirkia

+1

HereOrCode avatar Apr 10 '24 01:04 HereOrCode

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
  }}
/>;

HereOrCode avatar Apr 21 '24 11:04 HereOrCode

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:''}]}/>

QastanFIT avatar Apr 25 '24 08:04 QastanFIT