ComponentsForms & inputs

Color picker

Choose a colour — website brand colour, label colours, campaign or chart series colour. A saturation/brightness area and hue strip (keyboard sliders), an optional opacity strip, a value field that accepts hex, rgb() and oklch(), swatches as a radio group, the screen eyedropper where supported, and a WCAG contrast hint. The value is always hex.

react-colorful + Radix Popover / Radio Group components/color-picker.tsx, lib/color.ts, components/radio-group.tsx, components/popover.tsx, styles/forms.csstheme · material · accent · density · font

Used for buttons, links and the booking widget.

Installation

$ pnpm add @vamos-ui/react

The whole kit as one package — get updates by bumping the version. Add the styles to globals.css: @import "@vamos-ui/react/styles.css";

Usage

import { ColorPicker, ColorSwatchPicker, Field } from "@vamos-ui/react";

<Field label="Brand color">
  <ColorPicker name="brand" defaultValue="#2f6fd6" contrastAgainst="#ffffff" />
</Field>

<ColorSwatchPicker swatches={[{ value: "#1a9c8c", name: "Teal" }, …]} />

The area and strips are role=slider with dictionary names (“Saturation and brightness”, “Hue”, “Opacity”) and work with arrow keys.

Typing a hex value applies it as soon as it has 6 or 8 digits; rgb() and oklch() apply when they parse. Invalid text shows an error on blur and leaves the colour unchanged.

Examples

Swatches only (labels)

ColorSwatchPicker is a radio group: one tab stop, arrow keys move and select, each swatch is named (“Teal, #1a9c8c”).

PreviewFollow-up

With opacity (site overlay)

alpha adds an opacity strip; the value becomes #rrggbbaa when not fully opaque. Previews sit on an opaque checkerboard, never on blurred glass.

Darkens the cover image so the headline stays readable.

Contrast hint (website button)

contrastAgainst shows the WCAG ratio and AA/AAA rating for text in that colour. swatches="tokens" offers the theme palette.

White text needs 4.5:1 for normal-size labels.

Inline (theme settings)

variant="inline" renders the panel in place. The format switch edits in HEX, RGB or OKLCH; the stored value stays hex.

Contrast with #12150f14.3:1AAA
Preview

Spring menu is here

Twelve new dishes from the Aegean coast, served from 18:00.

Reserve

Sizes & states

sm / md / lg, read-only (doesn't open), disabled, Field error, and transparent.

Inherited from the parent brand.

This color is reserved for alerts.

API

ColorPicker

PropTypeDefault
value / defaultValue
"#rrggbb", or "#rrggbbaa" with alpha.
string"#000000"
onValueChange
Called with lowercase hex.
(hex: string) => void—
alpha
Opacity strip.
booleanfalse
swatches
Presets under the picker; "tokens" resolves the theme palette in the browser.
{ value, name? }[] | "tokens"—
format / defaultFormat / onFormatChange
Display and input format (value stays hex).
"hex" | "rgb" | "oklch""hex"
showFormats
Show the HEX / RGB / OKLCH switch.
booleantrue
contrastAgainst
Colour to compare with (e.g. the text colour); shows the WCAG ratio.
string—
eyeDropper
Screen picker button where the EyeDropper API exists.
booleantrue
variant
Swatch button + floating panel, or the panel in place.
"popover" | "inline""popover"
size
Trigger height.
"sm" | "md" | "lg""md"
name
Hidden input with the hex value.
string—
disabled / readOnly / invalid
Also inherited from Field.
boolean—
open / defaultOpen / onOpenChange
Control the popover.
boolean / (open) => void—
labels
dialog, area, hue, alpha, input, format, swatches, swatch, eyeDropper, invalid, contrast, ratio, aaa, aa, aaLarge, fail, transparent.
Partial<ColorPickerLabels>—

ColorSwatchPicker

PropTypeDefault
swatches
Required.
{ value, name? }[] | "tokens"—
value / defaultValue / onValueChange
Selected swatch.
string | null / (hex) => void—
size
20 / 28 px swatches.
"sm" | "md""md"
name / disabled
Form submission; inherited from Field.
string / boolean—

ColorPickerPanel

PropTypeDefault
value / onValueChange
Required. The picker body for your own popover or sheet.
string / (hex) => void—
alpha / swatches / format / contrastAgainst / eyeDropper / disabled
Same meaning as on ColorPicker.
as ColorPicker—

lib/color helpers

PropTypeDefault
parseColor(input)
hex (with or without #), rgb()/rgba(), oklch().
→ { r, g, b, a } | null—
toHex(input) / formatColor(hex, format)
Normalise to hex · format as hex, rgb() or oklch().
→ string—
contrastRatio(a, b) / contrastLevel(ratio) / readableOn(bg)
WCAG 2 contrast.
→ number · AAA|AA|AA-large|fail · #000/#fff—