# React Color Picker: HEX, RGB, HSL, Pipette und OKLCH

> So baust du einen React Color Picker mit HEX-, RGB- und HSL-Feldern, Swatches, Deckkraft und EyeDropper API und nutzt den Wert für OKLCH-Tokens in Tailwind v4.

- Autor: [Serban Rusu](https://wingo-ui.com/blog/authors/serban), Founder of Wingo UI
- Veröffentlicht: 16. Okt. 2026
- Kategorie: [Komponenten-Guides](https://wingo-ui.com/de/blog/category/components)
- Lesezeit: 9 Min.
- Kanonische URL: https://wingo-ui.com/de/blog/react-color-picker
- Englische Fassung: https://wingo-ui.com/blog/react-color-picker

## Kurz gesagt

Ein React Color Picker braucht ein Feld für Sättigung und Helligkeit mit Farbton-Leiste, Textfelder für HEX, RGB und HSL, vordefinierte Swatches, volle Tastaturbedienung und ein Layout fürs Smartphone, dazu die EyeDropper API, wo Chrome und Edge sie anbieten. Speichere den Wert als Hex-String und leite OKLCH in CSS mit Relative Color Syntax ab, denn der Picker arbeitet in sRGB. Der Color Picker (Pro) von Wingo UI bringt all das mit, außerdem getrennte Callbacks für Live-Änderungen und den finalen Wert sowie auf Smartphones ein Bottom Sheet mit Fertig-Button.

Ein React Color Picker wirkt wie eine Aufgabe fürs Wochenende, bis du aufschreibst, was Nutzer erwarten: ein Farbfeld zum Ziehen, eine Farbton-Leiste, ein Textfeld, in das eine Designerin `#FC4C01` einfügt, RGB- oder HSL-Kanäle für den Entwickler, der in Zahlen denkt, Markenfarben als Swatches, Deckkraft, eine Pipette, die eine Farbe aus dem Logo holt, Tastaturbedienung und etwas, das auf dem Smartphone funktioniert. Danach muss der Wert in einem Designsystem landen, das in Tailwind CSS v4 in OKLCH geschrieben ist. Dieser Guide zeigt jeden Teil am [Color Picker](https://wingo-ui.com/components/color-picker) von Wingo UI. Wir bauen diese Bibliothek selbst, neutral sind wir also nicht. Externe Fakten sind mit ihrer Quelle verlinkt und datiert.

## Was muss ein React Color Picker können?

Ein vollständiger Picker hat ein Feld für Sättigung und Helligkeit, eine Farbton-Leiste, Textfelder für HEX, RGB und HSL, vordefinierte Swatches, Tastaturbedienung auf jeder Fläche und ein Layout fürs Smartphone. Deckkraft und Pipette sind die beiden optionalen Teile. Kleine Bibliotheken wie [react-colorful](https://github.com/omgovich/react-colorful) (3,1 KB gzipped und ohne Abhängigkeiten, laut README im Oktober 2026) liefern dir die Flächen zum Ziehen und ein Hex-Feld, den Rest baust du selbst. Diese Checkliste gilt für jeden Farbwähler in React, egal welchen Weg du nimmst:

- **Ein Feld für Sättigung und Helligkeit plus eine Farbton-Leiste.** Das ist das HSV-Modell und der schnellste Weg, Farben zu erkunden.
- **Textfelder für HEX, RGB und HSL.** Leute fügen Werte aus Figma, einem Styleguide oder den DevTools ein. Jedes Eingabefeld eines React Color Pickers sollte eingefügten Text annehmen und Unsinn ablehnen, ohne die letzte gültige Farbe zu verlieren.
- **Swatches**, denn die meisten echten Entscheidungen lauten „eine unserer acht Markenfarben“.
- **Deckkraft** für Schatten und Overlays, standardmäßig aus.
- **Eine Pipette**, wo der Browser eine hat.
- **Tastaturbedienung** für das Farbfeld und die Leisten, nicht nur für die Textfelder.
- **Ein Layout fürs Smartphone**, denn ein 288px breites Popover lässt sich mit dem Daumen schlecht bedienen.

## Hat shadcn/ui einen Color Picker?

Nein. Stand 16. Oktober 2026 listet die [Komponentenseite von shadcn/ui](https://ui.shadcn.com/docs/components) Popover, Slider, Input und Toggle Group, aber keinen Color Picker, und empfiehlt für Community-Komponenten das eigene Registry-Verzeichnis. Ein shadcn Color Picker entsteht also durch Komposition: ein Popover, Slider für Farbton und Alpha, eine eigene 2D-Fläche (Radix hat keinen 2D-Slider), ein Eingabefeld mit eigenem Parser und Buttons für die Swatches.

Die Komponente von Wingo UI ist genauso gebaut, auf Radix Popover und Radix Slider, und wird mit einer CLI im shadcn-Stil als Quellcode installiert. Die Dateien gehören also dir, du kannst sie lesen und ändern:

```bash
npx wingo-ui@latest add color-picker
```

Der Befehl holt auch alles, was die Komponente importiert: [Field](https://wingo-ui.com/components/field) für Label und Fehlermeldung, [Drawer](https://wingo-ui.com/components/drawer) für das Sheet auf dem Smartphone, [Segmented Control](https://wingo-ui.com/components/segmented-control) für den Umschalter HEX / RGB / HSL, Button und die kleinen Helfer, die sie mit dem Rest der Bibliothek teilt (Controllable State, Media Queries, Motion-Presets und Defaults über `UIProvider`).

## Wie nutzt du den Color Picker in React?

Rendere `ColorPicker` mit einem Label und einem Wert. Er zeigt ein Eingabefeld, und ein Klick darauf öffnet ein Panel mit dem Farbfeld, der Farbton-Leiste, dem Format-Umschalter, den Eingabefeldern und 16 Standard-Swatches.

```tsx
"use client"

import { useState } from "react"
import { ColorPicker } from "@/components/ui/color-picker"

export function StoreColor({ onSave }: { onSave: (color: string) => void }) {
  const [color, setColor] = useState("#FC4C01")

  return (
    <ColorPicker
      label="Primärfarbe"
      description="Die Buttons und Links im Shop nutzen diese Farbe."
      value={color}
      onValueChange={setColor}
      onValueCommit={onSave}
      name="primary_color"
    />
  )
}
```

Zwei Callbacks sind hier wichtig. `onValueChange` feuert live beim Ziehen, höchstens einmal pro Animation Frame, damit eine Vorschau dem Daumen folgen kann. `onValueCommit` feuert, wenn die Änderung feststeht: beim Loslassen, bei Enter oder Blur in einem Textfeld, beim Tippen auf einen Swatch, bei einem Pick mit der Pipette, bei einer Taste im Farbfeld oder beim Fertig-Button im Sheet auf dem Smartphone. Speichere erst im zweiten Callback, sonst schickt ein einziges Ziehen Dutzende Requests. Die Prop `name` rendert ein verstecktes Eingabefeld, so liest ein natives Formular oder eine Server Action die Farbe mit `formData.get("primary_color")`.

Probier es unten aus: Zieh im Farbfeld, wechsle dann zu RGB und tipp einen Wert ein. Ungültiger Text färbt das Feld rot, und der Wert springt zur letzten gültigen Farbe zurück.

> Live-Demo (Color Picker): Zieh im Farbfeld und in der Farbton-Leiste, wechsle dann zu RGB oder HSL und tipp einen Wert ein: Er wird bei Enter übernommen, und die Shop-Vorschau folgt. Probier sie unter [Color Picker](https://wingo-ui.com/components/color-picker) aus und installier sie mit `npx wingo-ui@latest add color-picker`.

## Wie verhalten sich die Felder für HEX, RGB und HSL?

Die Prop `format` (`"hex"`, `"rgb"` oder `"hsl"`, Standard `"hex"`) legt fest, welchen String der Picker ausgibt und welche Felder das Panel zuerst zeigt. Der Umschalter im Panel ändert nur, welche Felder sichtbar sind. Nutzer können also RGB-Kanäle eintippen, während dein State weiter Hex bekommt. Die Ausgabe hat immer genau diese Form: `"#FC4C01"`, `"rgb(252, 76, 1)"` und `"hsl(18, 99%, 50%)"`.

Ein paar Details ersparen dir Support-Tickets:

- Ein dreistelliger Hex-Wert wird erweitert, `F60` ergibt also `#FF6600`. Das `#` ist optional.
- ArrowUp und ArrowDown in einem Zahlenfeld ändern den Wert um 1, mit Shift um 10.
- `defaultValue` und `value` nehmen jede Farbe an, die der Parser liest: Hex mit 3, 4, 6 oder 8 Stellen, `rgb()` / `rgba()`, `hsl()` / `hsla()` mit Kommas oder Leerzeichen und die Namen der 16 CSS-Grundfarben. Der Parser braucht kein Canvas und läuft deshalb auch auf dem Server.

Dieselben Umrechnungen sind für deinen eigenen Code exportiert. `parseColor(text)` gibt ein `Hsva` oder `null` zurück, und `formatColor(hsva, format, alpha)` macht daraus wieder einen String:

```ts
import { formatColor, parseColor } from "@/components/ui/color-picker"

const parsed = parseColor("rgb(252 76 1)")
const hex = parsed ? formatColor(parsed, "hex") : null // "#FC4C01"
```

## Wie fügst du Deckkraft und Markenfarben hinzu?

Schalte `alpha` ein, wenn Werte Transparenz brauchen. Das fügt eine Leiste und ein Feld für die Deckkraft hinzu. Hex wird unter 100% zu `#RRGGBBAA`, rgb und hsl werden immer zu `rgba()` / `hsla()`. So behält der String sein Format, während sich der Slider bewegt.

> Live-Demo (Color Picker): Zieh an der Deckkraft-Leiste: Das Format ist rgb mit Alpha, also wird der Wert zu rgba(), und das Schachbrettmuster scheint durch den Swatch. Probier sie unter [Color Picker](https://wingo-ui.com/components/color-picker) aus und installier sie mit `npx wingo-ui@latest add color-picker`.

Für eine Markenpalette übergibst du `swatches`. Der Standard ist das exportierte `COLOR_PICKER_SWATCHES` (16 Farben, erst Grautöne, dann Rot bis Pink). Du kannst es also erweitern oder ersetzen, und `[]` blendet die Reihe aus. Mit `showInputs={false}` verschwinden Textfelder, Format-Umschalter und Pipette. Übrig bleiben Farbfeld, Farbton-Leiste und deine Swatches:

```tsx
import { COLOR_PICKER_SWATCHES, ColorPicker } from "@/components/ui/color-picker"

const BRAND = ["#3B2A20", "#6F4E37", "#A67B5B", "#2F5D50", "#D9822B"]

export function LabelColors() {
  return (
    <>
      <ColorPicker label="Etikettenfarbe" swatches={BRAND} showInputs={false} radius="full" />
      <ColorPicker label="Hervorhebung" swatches={[...BRAND, ...COLOR_PICKER_SWATCHES]} />
    </>
  )
}
```

Die Swatches sind eine Radio Group: ein Tab-Stopp, Pfeiltasten zum Wechseln (ArrowUp und ArrowDown springen eine Reihe mit 8 Farben weiter) und ein Ring, der zur gewählten Farbe gleitet.

## Wie funktioniert die EyeDropper API in React?

Die [EyeDropper API](https://developer.mozilla.org/en-US/docs/Web/API/EyeDropper_API) öffnet die System-Pipette: `new EyeDropper().open()` liefert `{ sRGBHex }`, sobald jemand auf ein Pixel klickt. MDN führt sie als experimentell, und sie läuft nur in sicheren Kontexten (Secure Contexts). Laut der [Referenz von MDN zu open()](https://developer.mozilla.org/en-US/docs/Web/API/EyeDropper/open) wird das Promise abgelehnt: mit `AbortError` bei Escape oder einem abgebrochenen Signal, mit `NotAllowedError`, wenn der Aufruf nicht aus einer Nutzergeste kommt, und mit `InvalidStateError`, wenn schon eine andere Pipette offen ist. Stand Oktober 2026 führt [caniuse](https://caniuse.com/mdn-api_eyedropper) Unterstützung in Chrome und Edge ab 95 und Opera ab 81 auf dem Desktop, aber keine in Safari, Firefox oder Chrome für Android.

Wenn du einen React Color Picker mit Eyedropper selbst baust, gehen oft drei Dinge schief:

1. `window.EyeDropper` wird beim Rendern gelesen. Das stürzt auf dem Server ab oder führt zu einem Hydration Mismatch. Prüf die API erst nach dem Mount.
2. In Safari erscheint ein Button, der nichts tut. Blende ihn aus, wo die API fehlt.
3. Die System-Pipette bleibt offen, wenn dein Popover schließt. Gib `open()` ein `AbortSignal` mit und brich beim Unmount ab.

Eine minimale Version, die alle drei Fehler vermeidet:

```tsx
"use client"

import { useEffect, useRef, useSyncExternalStore } from "react"

type EyeDropperCtor = new () => { open: (o?: { signal?: AbortSignal }) => Promise<{ sRGBHex: string }> }

const subscribe = () => () => {}

export function EyeDropperButton({ onPick }: { onPick: (hex: string) => void }) {
  // false auf dem Server und bei der Hydration, danach die echte Antwort
  const supported = useSyncExternalStore(subscribe, () => "EyeDropper" in window, () => false)
  const abort = useRef<AbortController | null>(null)
  useEffect(() => () => abort.current?.abort(), [])

  if (!supported) return null

  const pick = async () => {
    if (abort.current) return // ein zweites open() würde InvalidStateError werfen
    const controller = new AbortController()
    abort.current = controller
    try {
      const EyeDropper = (window as unknown as { EyeDropper: EyeDropperCtor }).EyeDropper
      const { sRGBHex } = await new EyeDropper().open({ signal: controller.signal })
      onPick(sRGBHex)
    } catch {
      // AbortError: Escape oder Unmount
    } finally {
      abort.current = null
    }
  }

  return (
    <button type="button" onClick={pick}>
      Farbe vom Bildschirm wählen
    </button>
  )
}
```

Der Picker von Wingo UI macht intern dasselbe: Die Pipette erscheint nur, wo `window.EyeDropper` existiert, das Schließen des Panels bricht einen laufenden Pick ab, und das Popover ignoriert Klicks außerhalb, solange die System-Pipette offen ist. Der Klick, der ein Pixel wählt, schließt das Panel also nicht. Abschalten kannst du sie mit `showEyeDropper={false}`.

## Wie passt ein React Color Picker zu OKLCH-Tokens in Tailwind v4?

Speichere die Farbe, die Nutzer wählen, als Hex und lass CSS daraus OKLCH ableiten. Die Standardpalette von Tailwind v4 ist in OKLCH geschrieben (`--color-red-500: oklch(63.7% 0.237 25.331)` in der [Doku zu Farben](https://tailwindcss.com/docs/colors), geprüft im Oktober 2026), während der Picker in sRGB arbeitet und sein Parser keine `oklch()`-Strings liest. Die beiden Hälften lassen sich sauber trennen:

- **Hex ist das Speicherformat.** Das gibt der Picker aus, das fügen Leute ein, und das liefert die EyeDropper API (`sRGBHex`).
- **OKLCH wird in CSS abgeleitet.** Relative Color Syntax rechnet beim Rendern um: `oklch(from #FC4C01 l c h)` ist diese Farbe in OKLCH, und du kannst einen Kanal ändern, etwa die Helligkeit, und die übrigen beibehalten. [Caniuse](https://caniuse.com/css-relative-colors) führt Stand Oktober 2026 volle Unterstützung in Chrome und Edge 131, Safari 18 und Firefox 133.

Der kostenlose Helfer `colorVars` in `@/lib/tones` von Wingo UI macht genau das, und die Prop `color` von Button läuft durch ihn. Er erzeugt aus einem String fünf Tone-Variablen und wählt schwarzen oder weißen Text anhand der OKLCH-Helligkeit:

```ts
"--tone-foreground": `oklch(from ${color} clamp(0, (0.7 - l) * 1000, 1) 0 0)`,
"--tone-soft": `color-mix(in oklab, ${color} 14%, transparent)`,
```

So kann eine vom Nutzer gewählte Farbe einen einzelnen Button mit `<Button color={color}>` umfärben oder zur Laufzeit den ganzen Brand-Tone, ohne Build-Schritt:

```tsx
import type { CSSProperties, ReactNode } from "react"

export function BrandScope({ color, children }: { color: string; children: ReactNode }) {
  const style = {
    "--brand": color,
    "--brand-foreground": `oklch(from ${color} clamp(0, (0.7 - l) * 1000, 1) 0 0)`,
    "--brand-soft": `color-mix(in oklab, ${color} 14%, transparent)`,
    "--brand-soft-foreground": `color-mix(in oklab, ${color} 72%, var(--foreground))`,
  } as CSSProperties

  return <div style={style}>{children}</div>
}
```

Jede Komponente mit `tone="brand"` und jede `bg-brand`-Utility im Wrapper übernimmt die neue Farbe. Eine Bedingung gibt es: Der Override erreicht die Utilities nur, wenn das Theme sie mit `@theme inline { --color-brand: var(--brand); }` verknüpft, und genau das tut die `globals.css` von Wingo UI. Mit normalem `@theme` wird `var(--brand)` einmal auf `:root` aufgelöst, und ein Wrapper, der `--brand` neu setzt, ändert für `bg-brand` nichts.

Willst du in deinem React Color Picker OKLCH-Werte anzeigen oder brauchst du die Zahlen für eine Token-Datei, dann rechne das RGB des Pickers in JavaScript mit den [OKLab-Matrizen von Björn Ottosson](https://bottosson.github.io/posts/oklab/) um:

```ts
import { hsvaToRgba, parseColor } from "@/components/ui/color-picker"

const linear = (c: number) => {
  const v = c / 255
  return v <= 0.04045 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2.4
}

export function toOklch(color: string) {
  const hsva = parseColor(color)
  if (!hsva) return null
  const { r, g, b } = hsvaToRgba(hsva)
  const [lr, lg, lb] = [r, g, b].map(linear)
  const l = Math.cbrt(0.4122214708 * lr + 0.5363325363 * lg + 0.0514459929 * lb)
  const m = Math.cbrt(0.2119034982 * lr + 0.6806995451 * lg + 0.1073969566 * lb)
  const s = Math.cbrt(0.0883024619 * lr + 0.2817188376 * lg + 0.6299787005 * lb)
  const L = 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s
  const A = 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s
  const B = 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s
  const C = Math.hypot(A, B)
  const H = C < 0.0001 ? 0 : ((Math.atan2(B, A) * 180) / Math.PI + 360) % 360
  return `oklch(${L.toFixed(4)} ${C.toFixed(4)} ${H.toFixed(2)})`
}

toOklch("#FC4C01") // "oklch(0.6617 0.2215 36.93)"
```

Eine ehrliche Grenze: Hex kann nur sRGB beschreiben. Laut dem [Release-Post zu Tailwind v4](https://tailwindcss.com/blog/tailwindcss-v4) nutzt die OKLCH-Palette einen größeren Farbraum, damit die Farben kräftiger wirken, als sRGB es erlaubte. Wählst du eine dieser Farben auf einem P3-Bildschirm, bekommst du also den nächstliegenden sRGB-Hexwert, nicht den ursprünglichen Wert. Schreib Tokens mit erweitertem Farbraum von Hand in CSS und nutze den Picker für die Farben, die Nutzer wählen. Wie die Token-Ebenen zusammenspielen, erklärt unser Guide zu [Design Tokens in Tailwind v4](https://wingo-ui.com/de/blog/tailwind-v4-design-tokens).

## Ist der Color Picker per Tastatur bedienbar?

Ja. Das Farbfeld und die Leisten sind eigene Elemente mit `role="slider"`, und alle reagieren auf Tasten:

- Enter, Space oder ArrowDown auf dem Trigger öffnen das Panel und setzen den Fokus ins Farbfeld.
- Im Farbfeld ändern ArrowLeft und ArrowRight die Sättigung um 1%, ArrowUp und ArrowDown die Helligkeit (mit Shift um 10%), PageUp und PageDown ändern die Helligkeit in Schritten von 10%, und Home und End springen auf keine oder volle Sättigung.
- Die Leisten für Farbton und Deckkraft reagieren auf die Pfeiltasten, Home und End.
- Escape schließt das Panel und gibt den Fokus an den Trigger zurück. Hat ein Textfeld eine noch nicht übernommene Eingabe, setzt das erste Escape sie zurück und lässt das Panel offen.
- Screenreader lesen am Trigger das Label samt Wert vor („Primärfarbe, #FC4C01“), und jeden vorgelesenen Text kannst du über `labels` überschreiben.

## Wie funktioniert ein Color Picker auf dem Smartphone?

Unter 768px öffnet sich das Panel in einem Bottom Sheet statt in einem Popover: volle Breite, ein höheres Farbfeld, 28px große Griffe und größere Swatches. Änderungen im Sheet sind ein Entwurf, bis jemand auf Fertig tippt, und wer das Sheet wegzieht, behält die alte Farbe. `onValueChange` feuert dort erst bei Fertig, eine Live-Vorschau an anderer Stelle der Seite folgt dem Ziehen auf Smartphones also nicht. Setz `responsive={false}`, wenn du das Popover auch auf Smartphones willst. Das Muster und seine Kompromisse beschreibt unser Guide zum [React Bottom Sheet fürs Web](https://wingo-ui.com/de/blog/react-bottom-sheet-for-the-web).

## Kannst du das Panel in ein eigenes Popover oder direkt in die Seite einbauen?

Ja. Zwei Optionen decken die meisten Layouts ab:

- `inline` rendert das Panel direkt an Ort und Stelle, ohne Trigger und ohne Popover, für eine Einstellungsseite, auf der Änderungen sofort gelten.
- `ColorPickerPanel` ist nur das Panel, mit denselben Props `value`, `format`, `alpha`, `swatches` und `labels`, für deine eigene Fläche. Hier sitzt es im kostenlosen [Popover](https://wingo-ui.com/components/popover) hinter einem Button in der Toolbar:

```tsx
import { Palette } from "lucide-react"
import { Button } from "@/components/ui/button"
import { ColorPickerPanel } from "@/components/ui/color-picker"
import { Popover } from "@/components/ui/popover"

export function TextColorButton({ color, onChange }: { color: string; onChange: (c: string) => void }) {
  return (
    <Popover
      trigger={
        <Button variant="ghost" size="icon-sm" aria-label="Textfarbe">
          <Palette />
        </Button>
      }
      align="start"
      sheetTitle="Textfarbe"
    >
      <ColorPickerPanel value={color} onValueChange={onChange} showFormatSwitch={false} />
    </Popover>
  )
}
```

Für eine kompakte Toolbar ohne eigenes Popover macht `trigger="swatch"` aus dem Feld einen runden Button in der Größe eines Icon-Buttons.

## Was geht beim Speichern von Picker-Farben schief?

Drei Fehler fallen meist erst nach dem Launch auf, wenn echte Daten gespeichert sind:

- **Der Umweg über HSL.** Die `hsl()`-Ausgabe rundet jeden Kanal auf ganze Zahlen. Aus `#FC4C01` wird `hsl(18, 99%, 50%)`, und wieder eingelesen ergibt das `#FE4D01`. Speichere Hex oder rgb, wenn der genaue Wert zählt, und nutze hsl nur zur Anzeige.
- **Ein kontrollierter Wert in einem anderen Format.** Übergibst du `"rgb(252 76 1)"` mit `format="hex"`, zeigt der Picker den Wert wie übergeben und gibt bei der nächsten Änderung Hex aus. Normalisiere einmal mit `parseColor` und `formatColor`, wenn deine Datenbank eine einheitliche Form braucht.
- **Eine Markenfarbe mit schwachem Kontrast.** `colorVars` wechselt erst über einer OKLCH-Helligkeit von 0,7 auf schwarzen Text. `#FC4C01` liegt bei 0,66 und bekommt deshalb weißen Text mit einem Kontrastverhältnis von 3,4:1. Das liegt unter den 4,5:1, die WCAG AA für Fließtext verlangt (Schwarz käme auf 6,2:1). Prüf den Kontrast in `onValueCommit` vor dem Speichern und zeig das Problem über die Prop `error`, die die Beschreibung ersetzt und das Feld als ungültig markiert.

## Wo fängst du an?

Installiere den Picker und verbinde `onValueCommit` mit der Stelle, an der du das Theme speicherst:

```bash
npx wingo-ui@latest add color-picker
```

Der Color Picker gehört zu [Wingo UI Pro](https://wingo-ui.com/de/pricing); Popover, Field und Drawer, auf denen er aufbaut, sind kostenlos. Für den Rest des Formulars (Labels, Fehler, Validierung mit zod) lies unseren [Guide zu React-Formularkomponenten](https://wingo-ui.com/de/blog/react-form-components-guide). Die Kategorie [Komponenten-Guides](https://wingo-ui.com/de/blog/category/components) sammelt alle Beiträge dieser Art.

## Komponenten in diesem Artikel

- [Color Picker](https://wingo-ui.com/components/color-picker) (Pro): A React color picker with a saturation and brightness square, hue and opacity sliders, HEX / RGB / HSL inputs, swatches and an eyedropper. Installation: `npx wingo-ui@latest add color-picker`
- [Popover](https://wingo-ui.com/components/popover) (Free): A React popover for rich content anchored to a trigger, like a quick filter, form or share panel, that becomes a bottom sheet on phones. Installation: `npx wingo-ui@latest add popover`

## Häufige Fragen

### Hat shadcn/ui einen Color Picker?

Nein. Stand Oktober 2026 listet die Komponentenseite von shadcn/ui Popover, Slider und Input, aber keinen Color Picker, und verweist für Community-Komponenten auf das eigene Registry-Verzeichnis. Du baust ihn also aus diesen Teilen zusammen oder installierst eine fertige Komponente aus einer Registry.

### Welche Browser unterstützen die EyeDropper API?

Laut caniuse (Stand Oktober 2026) Chrome und Edge ab Version 95 und Opera ab Version 81 auf dem Desktop. Safari, Firefox und Chrome für Android unterstützen sie nicht, also prüfst du window.EyeDropper nach dem Mount und blendest den Button aus, wo die API fehlt.

### Kann ein React Color Picker OKLCH ausgeben?

Der Picker von Wingo UI gibt hex, rgb() oder hsl() aus, weil er in sRGB arbeitet, und die Picker von react-colorful decken laut README im Oktober 2026 nur HEX, RGB, HSL und HSV ab. Wandle in CSS mit oklch(from #FC4C01 l c h) um oder in JavaScript mit den OKLab-Formeln von Björn Ottosson, und schreib Tokens mit erweitertem Farbraum (Wide Gamut) von Hand in CSS.

### Wie speichere ich die Farbe erst, wenn das Ziehen vorbei ist?

Nutze zwei Callbacks: onValueChange für die Live-Vorschau und onValueCommit zum Speichern. Der Color Picker von Wingo UI ruft onValueCommit in diesen Fällen auf: beim Loslassen, bei Enter oder Blur in einem Feld, bei einem Swatch, einem Pick mit der Pipette, einer Taste im Farbfeld oder beim Fertig-Button im Sheet auf dem Smartphone.

### Ist der Color Picker von Wingo UI kostenlos?

Nein, der Color Picker gehört zu Wingo UI Pro. Popover, Field, Drawer, Segmented Control und Button, auf denen er aufbaut, sind kostenlos.

---

Quelle: https://wingo-ui.com/de/blog/react-color-picker
