Skip to content
Components

Color Picker

BetaBeta — the props contract is close to final, but small breaking changes can still land.

Color input with picker UI, formats, presets, contrast helpers, and a gradient editor with draggable stops.

Examples

Inline panel

Render the editor in place with ColorPickerPanel when the color is the main task, like a theme or brand settings page.

Color wheel

The wheel sets hue by angle and saturation by distance from the center; the brightness strip completes the color.

Inline strips

Each strip edits one coordinate of the same color, so the parts fit a toolbar or inspector row without a popup.

Gradient editor

Drag stops along the track, pick each stop color with the same picker, and read back a CSS gradient.

Composition

Popup color editor

Area, Channels, and Swatches supply their default children when omitted. AreaContrast draws the WCAG threshold for a background over the area.

  • <ColorPicker>
    • <ColorPickerTrigger />
    • <ColorPickerOutput />
    • <ColorPickerContent>
      • <ColorPickerArea>
        • <ColorPickerAreaContrast />
        • <ColorPickerAreaThumb />
        </ColorPickerArea>
      • <ColorPickerEyeDropper />
      • <ColorPickerHue />
      • <ColorPickerAlpha />
      • <ColorPickerFormatSelect />
      • <ColorPickerInput />
      • <ColorPickerChannels>
        • <ColorPickerChannel />
        </ColorPickerChannels>
      • <ColorPickerContrast />
      • <ColorPickerSwatches>
        • <ColorPickerSwatch />
        • <ColorPickerSwatchAdd />
        </ColorPickerSwatches>
      </ColorPickerContent>
    </ColorPicker>

Inline color wheel

  • <ColorPicker>
    • <ColorPickerPanel>
      • <ColorPickerWheel />
      • <ColorPickerBrightness />
      • <ColorPickerInput />
      </ColorPickerPanel>
    </ColorPicker>

Inline strips

Every strip edits one coordinate of the same color, so parts sit in a toolbar or inspector row without a popup.

  • <ColorPicker>
    • <ColorPickerSwatch />
    • <ColorPickerHue />
    • <ColorPickerSaturation />
    • <ColorPickerBrightness />
    • <ColorPickerOutput />
    </ColorPicker>

Gradient stops

Track renders a stop for each entry; supply children to customize those stops. The value is structured; formatGradient turns it into CSS.

  • <GradientEditor>
    • <GradientEditorPreview />
    • <GradientEditorTrack>
      • <GradientEditorStop />
      </GradientEditorTrack>
    • <GradientEditorStopColor />
    • <GradientEditorTypeSelect />
    • <GradientEditorInterpolationSelect />
    • <GradientEditorAngle />
    • <GradientEditorStopAdd />
    </GradientEditor>

Installation

The Control UI source installs this primitive from src/registry/sources/control-ui/ui/color-picker.tsx.

Registry command
See registry manifest

Dependencies

Color area drag hooksrc/registry/hooks/use-color-area.tsHook
Color enginesrc/registry/lib/color.tsSupport
WCAG contrastsrc/registry/lib/contrast.tsSupport
Gradientsrc/registry/lib/gradient.tsUtil
Color picker areasrc/registry/sources/control-ui/ui/color-picker-area.tsxSupport
Color picker contextsrc/registry/sources/control-ui/ui/color-picker-context.tsSupport
Color picker contrastsrc/registry/sources/control-ui/ui/color-picker-contrast.tsxSupport
Color picker sliderssrc/registry/sources/control-ui/ui/color-picker-sliders.tsxSupport
Color picker swatchessrc/registry/sources/control-ui/ui/color-picker-swatches.tsxSupport
Color picker valuessrc/registry/sources/control-ui/ui/color-picker-values.tsxSupport
Gradient editor controlssrc/registry/sources/control-ui/ui/gradient-editor-controls.tsxSupport
Gradient editorsrc/registry/sources/control-ui/ui/gradient-editor.tsxSupport
Surface variantssrc/registry/sources/control-ui/surface-variants.tsSupport
Control variantssrc/registry/sources/control-ui/control-variants.tsSupport
ButtonbuttonPrimitiveInputinputPrimitiveNumber Fieldnumber-fieldPrimitiveSelectselectPrimitive

Raw code

Primary installed source

src/registry/sources/control-ui/ui/color-picker.tsx

Knobs

Typed custom properties the recipe paints with. Set one on the root — style, a utility class, or a skin — and every slot inherits it.

--cui-color-picker-* · 7 knobsHow the cascade resolves
--cui-color-picker-output-swatch-radius<length-percentage>+var(--radius-md)
--cui-color-picker-swatch-radius<length-percentage>+var(--radius-md)
--cui-color-picker-area-radius<length-percentage>+var(--radius-field)
--cui-color-picker-trigger-radius<length-percentage>+var(--radius-control)
--cui-color-picker-trigger-shadow*inset 0 0 0 var(--control-rim-width) var(--control-rim)
--cui-color-picker-slider-thumb-radius<length-percentage>9999px
--cui-color-picker-slider-thumb-background<color>transparent
--cui-gradient-editor-* · 10 knobsHow the cascade resolves
--cui-gradient-editor-preview-radius<length-percentage>var(--radius-field)
--cui-gradient-editor-preview-ring-color<color>oklch(from var(--border) l c h / 0.6)
--cui-gradient-editor-track-radius<length-percentage>9999px
--cui-gradient-editor-stop-radius<length-percentage>9999px
--cui-gradient-editor-stop-border-color<color>oklch(1 0 0)
--cui-gradient-editor-stop-border-width<length>2px
--cui-gradient-editor-stop-shadow*0 0 0 1px oklch(from var(--foreground) l c h / 0.4)
--cui-gradient-editor-add-radius<length-percentage>9999px
--cui-gradient-editor-add-border-color<color>var(--border)
--cui-gradient-editor-add-border-width<length>var(--control-rim-width)
--cui-popup-* · 44 knobsHow the cascade resolves
--cui-popup-title-foreground<color>var(--cui-popup-foreground)
--cui-popup-title-font-size<length-percentage>var(--text-heading-3)
--cui-popup-title-font-weight<number>var(--font-weight-semibold)
--cui-popup-title-line-height<number>var(--text-heading-3--line-height)
--cui-popup-title-letter-spacing<length>-0.025em
--cui-popup-description-foreground<color>var(--muted-foreground)
--cui-popup-close-inset<length-percentage>calc(var(--spacing) * 3)
--cui-popup-item-inset<length-percentage>calc(var(--spacing) * 8)
--cui-popup-label-padding-block<length-percentage>var(--cui-popup-item-padding-block)
--cui-popup-label-padding-inline<length-percentage>var(--cui-popup-item-padding-inline)
--cui-popup-label-font-size<length-percentage>var(--text-micro)
--cui-popup-label-font-weight<number>var(--font-weight-medium)
--cui-popup-label-letter-spacing<length>0.08em
--cui-popup-label-text-transformnone | uppercase | lowercase | capitalizeuppercase
--cui-popup-separator-inset<length-percentage>calc(var(--popover-padding) * -1)
--cui-popup-shortcut-font-size<length-percentage>var(--text-body)
--cui-popup-shortcut-letter-spacing<length>0.02em
--cui-popup-status-success-foreground<color>var(--success-text)
--cui-popup-status-warning-foreground<color>var(--warning-text)
--cui-popup-status-info-foreground<color>var(--info-text)
--cui-popup-status-error-foreground<color>var(--destructive)
--cui-popup-radius<length-percentage>var(--radius-popover)
--cui-popup-background<color>var(--popover)
--cui-popup-foreground<color>var(--popover-foreground)
--cui-popup-border-color<color>var(--control-rim)
--cui-popup-border-width<length>var(--control-rim-width)
--cui-popup-shadow*var(--shadow-pop)
--cui-popup-backdrop-filter*blur(var(--backdrop-blur-popover))
--cui-popup-backdrop-background<color>oklch(from var(--foreground) l c h / var(--overlay-opacity))
--cui-popup-backdrop-blur<length>var(--backdrop-blur-overlay)
--cui-popup-item-radius<length-percentage>var(--radius-popup-item-fit)
--cui-popup-item-font-size<length-percentage>var(--text-body)
--cui-popup-item-icon-size<length-percentage>1rem
--cui-popup-item-padding-block<length-percentage>calc(var(--spacing) * 1)
--cui-popup-item-padding-inline<length-percentage>calc(var(--padding-x) * 0.5)
--cui-popup-item-min-height<length-percentage>max(var(--target-min), var(--control-h-xs))
--cui-popup-item-highlight-shadow*inset 0 0 0 1px oklch(from var(--foreground) l c h / 0.35)
--cui-popup-item-foreground<color>var(--foreground)
--cui-popup-item-highlight-background<color>var(--hover-fill)
--cui-popup-item-highlight-foreground<color>var(--cui-popup-item-foreground)
--cui-popup-item-highlight-muted-foreground<color>var(--muted-foreground)
--cui-popup-item-disabled-opacity<number>var(--disabled-opacity)
--cui-popup-separator-color<color>var(--border)
--cui-popup-shortcut-foreground<color>var(--muted-foreground)