HextaUI

BetaVercel UI SDK 0.1.0-beta.1 üzerine kurulu. API’si değişebilir.

Color picker

Vercel UI SDK üzerinde doygunluk alanı, ton ve alfa kaydırıcıları, yazılabilen CSS renkleri, hazır renkler ve damlalık içeren bir renk seçici.

Bağımlılıklar
  • @tabler/icons-react
  • @ui-sdk/core
  • @ui-sdk/react
"use client"

import * as React from "react"

import {
  ColorPicker,
  ColorPickerArea,
  ColorPickerContent,
  ColorPickerEyeDropper,
  ColorPickerInput,
  ColorPickerPopover,
  ColorPickerSlider,
  ColorPickerSwatch,
  ColorPickerSwatches,
  ColorPickerSwatchItem,
  ColorPickerTrigger,
} from "@/components/ui/ui-sdk-color-picker"

const presets = [
  "#0f172a",
  "#ef4444",
  "#f97316",
  "#eab308",
  "#22c55e",
  "#14b8a6",
  "#0ea5e9",
  "#6366f1",
  "#a855f7",
  "#ec4899",
]

function UiSdkColorPickerDemo() {
  const [value, setValue] = React.useState("#6366f1")

  return (
    <ColorPicker
      aria-label="Accent color"
      value={value}
      onValueChange={setValue}
    >
      <ColorPickerPopover>
        <ColorPickerTrigger aria-label={`Accent color, ${value}`}>
          <ColorPickerSwatch />
          <span className="font-mono text-xs uppercase tabular-nums">
            {value}
          </span>
        </ColorPickerTrigger>
        <ColorPickerContent>
          <ColorPickerArea />
          <ColorPickerSlider channel="hue" />
          <div className="flex items-center gap-2">
            <ColorPickerInput aria-label="Hex" />
            <ColorPickerEyeDropper aria-label="Pick a color from the screen" />
          </div>
          <ColorPickerSwatches aria-label="Presets">
            {presets.map((preset) => (
              <ColorPickerSwatchItem key={preset} value={preset} />
            ))}
          </ColorPickerSwatches>
        </ColorPickerContent>
      </ColorPickerPopover>
    </ColorPicker>
  )
}

export { UiSdkColorPickerDemo }
pnpm dlx shadcn@latest add https://hextaui.com/r/ui-sdk-color-picker.json

Bileşeni, HextaUI tema token'larını ve bileşenin bağımlı olduğu tüm HextaUI bileşenlerini ekler.

UI SDK, ui-sdk adlı bir cascade katmanında kendi CSS’ini biraz ekler. Sınıflarınızın kazanması için bu katmanı genel stil dosyanızın en üstünde, Tailwind import’unun üzerinde tanımlayın.

@layer ui-sdk;

@import "tailwindcss";
import {
  ColorPicker,
  ColorPickerArea,
  ColorPickerInput,
  ColorPickerSlider,
  ColorPickerSwatch,
} from "@/components/ui/ui-sdk-color-picker"
<ColorPicker aria-label="Brand color" defaultValue="#0ea5e9">
  <ColorPickerArea />
  <ColorPickerSlider channel="hue" />
  <ColorPickerSwatch />
  <ColorPickerInput aria-label="Hex" />
</ColorPicker>

Değer bir CSS renk dizesidir. Tüm parçalar aynı rengi düzenler, bu yüzden yalnızca ihtiyacınız olan parçaları kullanın. ColorPickerArea ve ColorPickerSlider tutamaçlarını kendisi çizer. Seçiciyi aria-label ile ya da onu saran bir alanın etiketiyle adlandırın.

ColorPicker
├── ColorPickerArea
│   ├── ColorPickerAreaCanvas
│   └── ColorPickerAreaThumb
├── ColorPickerSlider
│   └── ColorPickerSliderThumb
├── ColorPickerSwatch
├── ColorPickerInput
├── ColorPickerChannelInput
├── ColorPickerEyeDropper
├── ColorPickerSwatches
│   └── ColorPickerSwatchItem
└── ColorPickerPopover
    ├── ColorPickerTrigger
    └── ColorPickerContent

Ayarlar sayfası ya da kenar çubuğu için parçaları popover olmadan yerinde gösterin.

import {
  ColorPicker,
  ColorPickerArea,
  ColorPickerInput,
  ColorPickerSlider,
  ColorPickerSwatch,
} from "@/components/ui/ui-sdk-color-picker"

function UiSdkColorPickerInline() {
  return (
    <ColorPicker aria-label="Brand color" defaultValue="#0ea5e9">
      <ColorPickerArea />
      <ColorPickerSlider channel="hue" />
      <div className="flex items-center gap-2">
        <ColorPickerSwatch />
        <ColorPickerInput aria-label="Hex" />
      </div>
    </ColorPicker>
  )
}

export { UiSdkColorPickerInline }

channel="alpha" olan bir kaydırıcı opaklığı düzenler. Rayı ve renk örneği rengin altına dama deseni çizer, böylece saydam bir renk saydam görünür.

import {
  ColorPicker,
  ColorPickerArea,
  ColorPickerInput,
  ColorPickerSlider,
  ColorPickerSwatch,
} from "@/components/ui/ui-sdk-color-picker"

function UiSdkColorPickerAlpha() {
  return (
    <ColorPicker
      aria-label="Overlay color"
      space="hsl"
      defaultValue="hsl(262 83% 58% / 0.6)"
    >
      <ColorPickerArea />
      <ColorPickerSlider channel="hue" />
      <ColorPickerSlider channel="alpha" />
      <div className="flex items-center gap-2">
        <ColorPickerSwatch />
        <ColorPickerInput aria-label="HSL" />
      </div>
    </ColorPicker>
  )
}

export { UiSdkColorPickerAlpha }

space="oklch" ile alanı boyamak için ColorPickerAreaCanvas ekleyin. Ekranın gamut’u dışındaki renkler boş kalır; oraya sürüklenen tutamaç bırakınca içerideki en yakın renge oturur.

import {
  ColorPicker,
  ColorPickerArea,
  ColorPickerAreaCanvas,
  ColorPickerAreaThumb,
  ColorPickerInput,
  ColorPickerSlider,
  ColorPickerSwatch,
} from "@/components/ui/ui-sdk-color-picker"

function UiSdkColorPickerOklch() {
  return (
    <ColorPicker
      aria-label="Accent"
      space="oklch"
      defaultValue="oklch(0.62 0.19 259)"
    >
      <ColorPickerArea>
        <ColorPickerAreaCanvas />
        <ColorPickerAreaThumb />
      </ColorPickerArea>
      <ColorPickerSlider channel="hue" />
      <div className="flex items-center gap-2">
        <ColorPickerSwatch />
        <ColorPickerInput aria-label="OKLCH" />
      </div>
    </ColorPicker>
  )
}

export { UiSdkColorPickerOklch }

ColorPickerSwatches hazır renkler arasında ok tuşlarıyla gezilen tek bir Tab durağıdır; değer nasıl yazılırsa yazılsın hazır renk seçili kalır. ColorPickerChannelInput tek bir kanalı sayı olarak düzenler. Damlalık, ekrandan renk alamayan tarayıcılarda kendini gizler.

import {
  ColorPicker,
  ColorPickerChannelInput,
  ColorPickerEyeDropper,
  ColorPickerSwatch,
  ColorPickerSwatches,
  ColorPickerSwatchItem,
} from "@/components/ui/ui-sdk-color-picker"

const presets = [
  "#ef4444",
  "#f97316",
  "#eab308",
  "#22c55e",
  "#0ea5e9",
  "#6366f1",
  "#a855f7",
  "#ec4899",
]

const channels = [
  { channel: "red", label: "R" },
  { channel: "green", label: "G" },
  { channel: "blue", label: "B" },
] as const

function UiSdkColorPickerChannels() {
  return (
    <ColorPicker
      aria-label="Label color"
      space="srgb"
      format="hex"
      defaultValue="#0ea5e9"
    >
      <ColorPickerSwatches aria-label="Presets">
        {presets.map((preset) => (
          <ColorPickerSwatchItem key={preset} value={preset} />
        ))}
      </ColorPickerSwatches>
      <div className="flex items-end gap-2">
        <ColorPickerSwatch />
        {channels.map(({ channel, label }) => (
          <label
            key={channel}
            className="flex min-w-0 flex-1 flex-col gap-1 text-xs text-muted-foreground"
          >
            {label}
            <ColorPickerChannelInput channel={channel} />
          </label>
        ))}
        <ColorPickerEyeDropper aria-label="Pick a color from the screen" />
      </div>
    </ColorPicker>
  )
}

export { UiSdkColorPickerChannels }

Bir kaydırıcıyı alanın yanına dikmek için orientation="vertical" verin.

import {
  ColorPicker,
  ColorPickerArea,
  ColorPickerSlider,
} from "@/components/ui/ui-sdk-color-picker"

function UiSdkColorPickerVertical() {
  return (
    <ColorPicker aria-label="Highlight" space="hsl" defaultValue="#f97316">
      <div className="flex gap-3">
        <div className="min-w-0 flex-1">
          <ColorPickerArea />
        </div>
        <ColorPickerSlider channel="hue" orientation="vertical" />
        <ColorPickerSlider channel="alpha" orientation="vertical" />
      </div>
    </ColorPicker>
  )
}

export { UiSdkColorPickerVertical }

onValueChange sürüklemenin her adımında, onValueCommit ise bittiğinde bir kez çalışır; kaydetmeyi orada yapın. createColorPickerController() ile oluşturulan bir controller rengi her yerden ayarlar.

"use client"

import * as React from "react"

import { Button } from "@/components/ui/button"
import {
  ColorPicker,
  ColorPickerArea,
  ColorPickerInput,
  ColorPickerSlider,
  createColorPickerController,
} from "@/components/ui/ui-sdk-color-picker"

function UiSdkColorPickerControlled() {
  const [picker] = React.useState(() => createColorPickerController())
  const [value, setValue] = React.useState("#0ea5e9")
  const [saved, setSaved] = React.useState("#0ea5e9")

  return (
    <div className="flex w-full max-w-64 flex-col gap-3">
      <ColorPicker
        aria-label="Theme color"
        value={value}
        onValueChange={setValue}
        onValueCommit={setSaved}
        controller={picker}
      >
        <ColorPickerArea />
        <ColorPickerSlider channel="hue" />
        <ColorPickerInput aria-label="Hex" />
      </ColorPicker>
      <div className="flex items-center justify-between gap-2 text-sm">
        <p className="text-muted-foreground">
          Saved <span className="font-mono text-foreground">{saved}</span>
        </p>
        <Button
          variant="outline"
          size="sm"
          onClick={() => picker.setValue("#663399")}
        >
          Use purple
        </Button>
      </div>
    </div>
  )
}

export { UiSdkColorPickerControlled }

Gizli bir input değeri name altında gönderir; form sıfırlanınca defaultValue değerine döner.

"use client"

import * as React from "react"

import { Button } from "@/components/ui/button"
import {
  ColorPicker,
  ColorPickerArea,
  ColorPickerSlider,
  ColorPickerSwatch,
} from "@/components/ui/ui-sdk-color-picker"

function UiSdkColorPickerForm() {
  const [submitted, setSubmitted] = React.useState<string | null>(null)

  return (
    <form
      className="flex w-full max-w-64 flex-col gap-3"
      onSubmit={(event) => {
        event.preventDefault()
        setSubmitted(String(new FormData(event.currentTarget).get("brand")))
      }}
      onReset={() => setSubmitted(null)}
    >
      <ColorPicker aria-label="Brand color" name="brand" defaultValue="#f97316">
        <ColorPickerArea />
        <div className="flex items-center gap-2">
          <ColorPickerSwatch />
          <div className="min-w-0 flex-1">
            <ColorPickerSlider channel="hue" />
          </div>
        </div>
      </ColorPicker>
      <div className="flex gap-2">
        <Button type="submit" size="sm">
          Save
        </Button>
        <Button type="reset" variant="outline" size="sm">
          Reset
        </Button>
      </div>
      <p role="status" className="text-sm text-muted-foreground">
        {submitted ? (
          <>
            Submitted brand=
            <span className="font-mono text-foreground">{submitted}</span>
          </>
        ) : (
          "Nothing submitted yet."
        )}
      </p>
    </form>
  )
}

export { UiSdkColorPickerForm }

Devre dışı bir seçici odak almaz, değişmez ve hiçbir şey göndermez.

import {
  ColorPicker,
  ColorPickerArea,
  ColorPickerInput,
  ColorPickerSlider,
} from "@/components/ui/ui-sdk-color-picker"

function UiSdkColorPickerDisabled() {
  return (
    <ColorPicker aria-label="Brand color" defaultValue="#0ea5e9" disabled>
      <ColorPickerArea />
      <ColorPickerSlider channel="hue" />
      <ColorPickerInput aria-label="Hex" />
    </ColorPicker>
  )
}

export { UiSdkColorPickerDisabled }

readOnly ile tutamaçlar odak alabilir ve değer gönderilir, ama sürükleme, tuşlar ve yazma rengi değiştirmez.

import {
  ColorPicker,
  ColorPickerArea,
  ColorPickerInput,
  ColorPickerSlider,
  ColorPickerSwatch,
} from "@/components/ui/ui-sdk-color-picker"

function UiSdkColorPickerReadOnly() {
  return (
    <ColorPicker aria-label="Theme color" defaultValue="#22c55e" readOnly>
      <ColorPickerArea />
      <ColorPickerSlider channel="hue" />
      <div className="flex items-center gap-2">
        <ColorPickerSwatch />
        <ColorPickerInput aria-label="Hex" />
      </div>
    </ColorPicker>
  )
}

export { UiSdkColorPickerReadOnly }

UI SDK yönü sayfadan okur; bu yüzden alan, kaydırıcılar ve ok tuşları aynalanır. Input’lar kendi yönünü seçer, böylece bir hex değeri yine soldan sağa okunur.

import {
  ColorPicker,
  ColorPickerArea,
  ColorPickerInput,
  ColorPickerSlider,
  ColorPickerSwatch,
} from "@/components/ui/ui-sdk-color-picker"

function UiSdkColorPickerRtl() {
  return (
    <div dir="rtl" className="flex w-full justify-center">
      <ColorPicker aria-label="لون العلامة" defaultValue="#ec4899">
        <ColorPickerArea />
        <ColorPickerSlider channel="hue" />
        <div className="flex items-center gap-2">
          <ColorPickerSwatch />
          <ColorPickerInput aria-label="سداسي عشري" />
        </div>
      </ColorPicker>
    </div>
  )
}

export { UiSdkColorPickerRtl }
TuşAction
←→↑↓Bir tutamacı bir adım taşır. Alanda sol ve sağ yatay, yukarı ve aşağı dikey hareket ettirir.
Shift + arrowOn adım taşır.
Page UpPage DownAralığın onda biri kadar, alanda yukarı ya da kaydırıcı boyunca ilerler.
HomeEndBaşa ya da sona taşır.
EnterInput’taki metni okur ya da odaktaki hazır rengi seçer.
EscInput’taki metni değere geri döndürür ya da popover’ı kapatır.

Renk seçiciyi karşılayan bir WAI-ARIA deseni yok, bu yüzden UI SDK onu var olan desenlerden kurar. Seçici bir gruptur. Alanın tutamacı ve her kaydırıcı tutamacı birer slider’dır; alanın tutamacı iki kanalını da adlandırır, örneğin “Doygunluk %76, Parlaklık %96”. Hazır renkler bir listbox’tır; her hazır renk ve renk örneği rengiyle adlandırılır, örneğin “canlı mavi”.

Popover örneğindeki tetikleyici, adında mevcut rengi söyler. Tutamaçlar yalnızca harekete izin verildiğinde sürüklerken büyür; dama deseni, halkalar ve odak çerçeveleri zorunlu renkler modunda sistem renklerine geçer.

Her parça aynı adlı UI SDK parçasını sarar ve render ile parçanın durumuna bağlı bir fonksiyon olabilen className dahil tüm prop’larını kabul eder.

PropTürVarsayılan
value
string–
defaultValue
string"black"
onValueChangeSürüklemenin her adımında, her tuşta, yazılan renkte ya da hazır renkte çalışır.
(value: string, details: ChangeDetails) => void–
onValueCommitBir sürükleme, tuş ya da yazılan renk bittiğinde bir kez çalışır.
(value: string, details: ChangeDetails) => void–
spaceParçaların hangi kanalları düzenlediği.
"hsv" | "hsl" | "srgb" | "oklch""hsv"
formatDeğerin nasıl yazıldığı. hsv için hex, diğerlerinde uzayın kendi CSS sözdizimi.
ColorFormat–
gamut
"srgb" | "p3" | false"srgb"
disabled
booleanfalse
readOnly
booleanfalse
required
booleanfalse
name
string–
form
string–
controllercreateColorPickerController() ile oluşturulur.
ColorPickerController–
render
ReactElement | (props, state) => ReactElement<div>
ÖznitelikAçıklama
data-slot="color-picker"CSS'te kökü hedefleyin.
data-disabledDevre dışıyken bulunur.
data-readonlySalt okunur olduğunda bulunur.
data-requiredZorunlu olduğunda bulunur.
data-out-of-gamutBir sürükleme gamut dışında bir renk tuttuğu sürece her parçada bulunur.
--color-picker-colorCSS olarak renk. Tutamaçlar ve renk örnekleri bununla dolar.
PropTürVarsayılan
xYatay kanal. Uzaya göre doygunluk, kırmızı ya da kroma.
ColorChannel–
yDikey kanal. Uzaya göre parlaklık, açıklık ya da yeşil.
ColorChannel–
children
ReactNode<ColorPickerAreaThumb />
render
ReactElement | (props, state) => ReactElement<div>
ÖznitelikAçıklama
data-slot="color-picker-area"Alanı CSS’te hedeflemek için.
--color-area-backgroundAlanı çizen gradyanlar. Alanı bir canvas boyuyorsa tanımsızdır.
--color-picker-radiusAlanın köşe yarıçapı. Köşeler eş merkezli olsun diye ColorPickerContent ayarlar.
ÖznitelikAçıklama
data-slot="color-picker-area-thumb"Tutamacı CSS’te hedeflemek için.
--area-xTutamacın alandaki yatay konumu, 0 ile 1 arası.
--area-yTutamacın alandaki dikey konumu, 0 ile 1 arası.
PropTürVarsayılan
channelVarsayılan olarak ton, sRGB’de ise mavi.
ColorChannel–
orientation
"horizontal" | "vertical""horizontal"
children
ReactNode<ColorPickerSliderThumb />
render
ReactElement | (props, state) => ReactElement<div>
ÖznitelikAçıklama
data-slot="color-picker-slider"Kaydırıcıyı CSS’te hedeflemek için.
data-channelDüzenlediği kanal, örneğin ton ya da alfa.
data-orientationhorizontal veya vertical.
--color-slider-backgroundKanal boyunca bir gradyan.
PropTürVarsayılan
channelDüzenlenecek kanal, insanların okuduğu birimlerle.
ColorChannel–
render
ReactElement | (props, state) => ReactElement<input>
PropTürVarsayılan
valueZorunlu. Hazır rengin rengi.
string–
render
ReactElement | (props, state) => ReactElement<button>
ÖznitelikAçıklama
data-slot="color-picker-swatch-item"Hazır renkleri CSS’te hedeflemek için.
data-selectedDeğer bu hazır rengin rengi olduğu sürece bulunur.
PropTürVarsayılan
children
ReactNode<IconColorPicker />
render
ReactElement | (props, state) => ReactElement<button>
ÖznitelikAçıklama
data-unsupportedTarayıcıda EyeDropper yoksa bulunur. Bu durumda düğme gizlenir.

ColorPickerPopover, ColorPickerTrigger ve ColorPickerContent UI SDK popover’ını sarar. İçerik tarayıcının top layer’ında açılır, bu yüzden portal gerekmez.

PropTürVarsayılan
side
"top" | "bottom" | "left" | "right" | "start" | "end""bottom"
align
"start" | "center" | "end""start"
sideOffset
number6
ÖznitelikAçıklama
data-slot="popover-content"UI SDK tarafından popup’a eklenir. CSS’te hedeflemek için kullanın.
data-starting-styleAçılır pencere animasyonla girerken bulunur.
data-ending-styleAçılır pencere animasyonla çıkarken bulunur.