ColorPicker

PreviousNext

A trigger with a color swatch opening a popover with a saturation/brightness surface, hue and alpha sliders, HEX/RGB/HSL inputs, an eyedropper, and preset swatches.

Fill
Stroke — rgb() in, hex out
Glow
<script setup lang="ts">
import { ref } from 'vue'
import { ColorPicker } from '@/components/ui/color-picker'

const fill = ref('#06b6d4')
const stroke = ref('rgb(244 63 94 / 0.6)')
const glow = ref('#f59e0b')
</script>

<template>
  <div class="flex max-w-sm flex-col gap-3">
    <div class="flex items-center gap-3">
      <ColorPicker v-model="fill" />
      <span class="text-muted-foreground text-xs/relaxed">Fill</span>
    </div>
    <div class="flex items-center gap-3">
      <ColorPicker v-model="stroke" />
      <span class="text-muted-foreground text-xs/relaxed">Stroke — rgb() in, hex out</span>
    </div>
    <div class="flex items-center gap-3">
      <ColorPicker v-model="glow" default-value="#8b5cf6" />
      <span class="text-muted-foreground text-xs/relaxed">Glow</span>
    </div>

    <svg viewBox="0 0 120 60" class="mt-1 h-16 w-full rounded-lg border border-border/60 bg-input/10">
      <rect
        x="20"
        y="12"
        width="80"
        height="36"
        rx="8"
        :fill="fill"
        :stroke="stroke"
        stroke-width="4"
        :filter="`drop-shadow(0 0 6px ${glow})`"
      />
    </svg>
  </div>
</template>

Installation

pnpm dlx hui-kit@latest add color-picker

Usage

<script setup lang="ts">
import { ref } from 'vue'
import { ColorPicker } from '@/components/ui/color-picker'

const color = ref('#3b82f6')
</script>

<template>
  <ColorPicker v-model="color" />
</template>

The value is always a string. Any CSS color is accepted on the way in — #06b6d4, rgb(6 182 212), hsl(187 94% 43%), even teal — and emitted back as #rrggbb, or #rrggbbaa when translucent.

Anatomy

The trigger shows the current swatch and hex value; everything else lives in the popover:

  • the saturation/value surface — drag anywhere, pointer capture included
  • the hue slider over the full spectrum
  • the alpha slider over a checkerboard
  • a HEX / RGB / HSL switch with compact channel inputs
  • an eyedropper button, rendered only where window.EyeDropper exists (Chromium)
  • fourteen preset swatches, one per hue family

Examples

Default value

Uncontrolled usage with default-value.

#10b981
<script setup lang="ts">
import { ref } from 'vue'
import { ColorPicker } from '@/components/ui/color-picker'

const accent = ref('#10b981')
</script>

<template>
  <div class="flex items-center gap-3">
    <ColorPicker v-model="accent" default-value="#8b5cf6" />
    <span class="text-muted-foreground text-xs/relaxed tabular-nums">{{ accent }}</span>
  </div>
</template>

Custom presets

Pass your own swatch list, or empty it out entirely.

Warm presets only
No preset strip
<script setup lang="ts">
import { ref } from 'vue'
import { ColorPicker, PRESET_COLORS } from '@/components/ui/color-picker'

const brand = ref('#ef4444')
const bare = ref('#f97316')
</script>

<template>
  <div class="flex flex-col gap-3">
    <div class="flex items-center gap-3">
      <ColorPicker v-model="brand" :presets="[...PRESET_COLORS.slice(0, 7)]" />
      <span class="text-muted-foreground text-xs/relaxed">Warm presets only</span>
    </div>
    <div class="flex items-center gap-3">
      <ColorPicker v-model="bare" :presets="[]" />
      <span class="text-muted-foreground text-xs/relaxed">No preset strip</span>
    </div>
  </div>
</template>