Skip to content

Color Picker

A color picker with a saturation/value area, channel sliders, channel inputs, and swatches. Channel parts read data-channel (on the part or a containing data-part="channel-slider"); swatches read data-value.

html
<div
  data-controller="zag-color-picker"
  data-part="root"
  data-zag-color-picker-value-value="#6366f1"
  class="relative inline-block"
>
  <button
    data-part="trigger"
    class="border-input bg-popover text-foreground hover:bg-accent inline-flex items-center rounded-lg border px-3 py-2 text-sm shadow-sm"
  >
    <span
      class="border-input block h-5 w-5 rounded border"
      style="background: var(--value, #6366f1)"
    ></span>
    <span data-part="value-text"></span>
  </button>
  <div data-part="positioner">
    <div
      data-part="content"
      hidden
      class="border-border bg-popover z-50 mt-1 w-56 space-y-3 rounded-lg border p-3 shadow-lg"
    >
      <div data-part="area" class="relative h-40 w-full rounded">
        <div data-part="area-background" class="h-full w-full rounded"></div>
        <div
          data-part="area-thumb"
          class="border-background absolute h-3 w-3 -translate-x-1/2 -translate-y-1/2 rounded-full border-2 shadow"
        ></div>
      </div>
      <div data-part="channel-slider" data-channel="hue" class="relative h-3 rounded-full">
        <div data-part="channel-slider-track" class="h-full w-full rounded-full"></div>
        <div
          data-part="channel-slider-thumb"
          class="border-background absolute h-3 w-3 -translate-x-1/2 rounded-full border-2 shadow"
        ></div>
      </div>
      <input
        data-part="channel-input"
        data-channel="hex"
        class="border-input text-foreground w-full rounded border px-2 py-1 text-sm focus:outline-none"
      />
    </div>
  </div>
  <input data-part="hidden-input" class="sr-only" />
</div>

Sizing the gradients

Zag sets position: relative inline on area-background and channel-slider-track, so fill their parent with h-full w-full — an absolute inset-0 would be defeated by that inline position and the element would collapse to zero height, showing no color. Give the area and channel-slider wrappers an explicit height (e.g. h-40, h-3).

Parts

root, label, control, trigger, value-text, positioner, content, area, area-background, area-thumb, channel-slider, channel-slider-track, channel-slider-thumb, channel-input, swatch-group, swatch, swatch-trigger, swatch-indicator, eye-dropper-trigger, hidden-input.

Values

AttributeTypeDefaultDescription
data-zag-color-picker-value-valueString"#000000"Initial color (hex).
data-zag-color-picker-format-valueString"rgba""rgba", "hsla", "hsba".
data-zag-color-picker-name-valueString""name for form submission.
data-zag-color-picker-open-valueBooleanfalseOpen by default.
data-zag-color-picker-inline-valueBooleanfalseAlways-open inline picker.
data-zag-color-picker-close-on-select-valueBooleanfalseClose after choosing a swatch.
data-zag-color-picker-disabled-valueBooleanfalseDisable the picker.
data-zag-color-picker-read-only-valueBooleanfalseRead-only.
data-zag-color-picker-required-valueBooleanfalseMark required.

Events

Emits zag-color-picker:change and :change-end ({ value, valueAsString }, value is hex) and :open-change.

Programmatic control

value (getter, hex), valueAsString (getter), setValue(color), open(), close(), isOpen.