Skip to content

Picker UI

A Picker UI color component to select a color.
vue
<script setup lang="ts">
import { Pipette } from "lucide-vue-next";
import {
  type ModeInput,
  PickerUiEyeDropperRoot,
  PickerUiEyeDropperTrigger,
  PickerUiModeContent,
  PickerUiModeItem,
  PickerUiModeItemInput,
  PickerUiModeItemLabel,
  PickerUiModeRoot,
  PickerUiModeTrigger,
  PickerUiRenderRoot,
  PickerUiRoot,
  PickerUiSliderAlphaRoot,
  PickerUiSliderAlphaThumb,
  PickerUiSliderColorRoot,
  PickerUiSliderColorThumb,
  PickerUiSliderMainRoot,
  PickerUiSliderMainThumb,
  PickerUiHistoryRoot,
  PickerUiHistoryList,
  PickerUiHistoryListItem
} from "color-ui-vue";
import { ref } from "vue";

const color = ref({ r: 49, g: 168, b: 94, a: 1 });
</script>

<template>
  <PickerUiRoot
    v-model="color"
    allowed-alpha
    :options="{ historyLimit: 7 }"
    class="flex flex-col w-80 gap-y-2 px-4 py-4 rounded-lg border bg-background"
  >
    <PickerUiSliderMainRoot class="group outline-none h-40 w-full mb-4 rounded-md">
      <PickerUiSliderMainThumb
        class="block h-4 w-4 rounded-full cursor-pointer data-[disabled=true]:cursor-not-allowed border-2 border-primary bg-background ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50"
      />
    </PickerUiSliderMainRoot>
    <div class="flex gap-x-2">
      <div class="flex gap-x-2">
        <PickerUiRenderRoot class="min-h-10 min-w-10 rounded-full" />
        <PickerUiEyeDropperRoot>
          <PickerUiEyeDropperTrigger
            class="h-10 w-full px-4 py-2 inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 border border-input bg-background hover:bg-accent hover:text-accent-foreground"
          >
            <Pipette class="w-4 h-4" />
          </PickerUiEyeDropperTrigger>
        </PickerUiEyeDropperRoot>
      </div>
      <div class="flex flex-col w-full items-center justify-center gap-y-2">
        <PickerUiSliderColorRoot
          class="relative flex touch-none select-none items-center justify-center rounded-full h-3 w-full"
        >
          <PickerUiSliderColorThumb
            class="block h-4 w-4 rounded-full border-2 border-primary bg-background ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50"
          />
        </PickerUiSliderColorRoot>
        <PickerUiSliderAlphaRoot
          class="relative flex touch-none select-none items-center justify-center rounded-full h-3 w-full"
        >
          <PickerUiSliderAlphaThumb
            class="block h-4 w-4 rounded-full border-2 border-primary bg-background ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50"
          />
        </PickerUiSliderAlphaRoot>
      </div>
    </div>
    <PickerUiModeRoot class="flex flex-col">
      <PickerUiModeContent
        v-for="mode in ['rgb', 'hsl'] as const"
        :value="mode"
        :key="'mode-' + mode"
        class="flex gap-x-2 w-full"
        v-slot="{ value }"
      >
        <PickerUiModeItem
          v-for="item in value"
          :key="'rgb-' + item"
          :value="item as ModeInput"
          class="flex flex-col text-center"
        >
          <PickerUiModeItemLabel>{{ item.toUpperCase() }}</PickerUiModeItemLabel>
          <PickerUiModeItemInput
            class="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
          />
        </PickerUiModeItem>
        <PickerUiModeItem value="a">
          <PickerUiModeItemLabel>A</PickerUiModeItemLabel>
          <PickerUiModeItemInput
            class="flex h-10 w-20 rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
          />
        </PickerUiModeItem>
      </PickerUiModeContent>
      <PickerUiModeContent value="hex" class="flex gap-x-2 w-full">
        <PickerUiModeItem value="hex" class="flex flex-col w-full">
          <PickerUiModeItemLabel>Hex</PickerUiModeItemLabel>
          <PickerUiModeItemInput
            class="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
          />
        </PickerUiModeItem>
        <PickerUiModeItem value="a">
          <PickerUiModeItemLabel>A</PickerUiModeItemLabel>
          <PickerUiModeItemInput
            class="flex h-10 w-20 rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
          />
        </PickerUiModeItem>
      </PickerUiModeContent>
      <PickerUiModeTrigger
        v-slot="{ mode }"
        class="mt-2 h-10 w-full px-4 py-2 inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 border border-input bg-background hover:bg-accent hover:text-accent-foreground"
      >
        {{ mode }}
      </PickerUiModeTrigger>
    </PickerUiModeRoot>
    <PickerUiHistoryRoot>
      <PickerUiHistoryList class="flex justify-between gap-x-2 mt-2">
        <PickerUiHistoryListItem class="h-8 w-8 rounded-md" />
      </PickerUiHistoryList>
    </PickerUiHistoryRoot>
  </PickerUiRoot>
</template>

<style scoped></style>

Installation

Install the component from your command line.

sh
$ npm add color-ui-vue

Anatomy

Import all parts and piece them together.

vue
<script setup lang="ts">
import {
  PickerUiRoot,
  PickerUiModeRoot,
  PickerUiModeContent,
  PickerUiModeTrigger,
  PickerUiModeItem,
  PickerUiModeItemLabel,
  PickerUiModeItemInput,
  PickerUiSliderMainRoot,
  PickerUiSliderMainThumb,
  PickerUiRenderRoot,
  PickerUiSliderColorRoot,
  PickerUiSliderColorThumb,
  PickerUiSliderAlphaRoot,
  PickerUiSliderAlphaThumb,
  PickerUiEyeDropperRoot,
  PickerUiEyeDropperTrigger
} from "color-ui-vue";
</script>

<template>
  <PickerUiRoot>
    <PickerUiSliderMainRoot>
      <PickerUiSliderMainThumb />
    </PickerUiSliderMainRoot>

    <PickerUiRenderRoot />

    <PickerUiEyeDropperRoot>
      <PickerUiEyeDropperTrigger />
    </PickerUiEyeDropperRoot>

    <PickerUiSliderColorRoot>
      <PickerUiSliderColorThumb />
    </PickerUiSliderColorRoot>

    <PickerUiSliderAlphaRoot>
      <PickerUiSliderAlphaThumb />
    </PickerUiSliderAlphaRoot>

    <PickerUiModeRoot>
      <PickerUiModeContent>
        <PickerUiModeItem>
          <PickerUiModeItemLabel />
          <PickerUiModeItemInput />
        </PickerUiModeItem>
      </PickerUiModeContent>
      <PickerUiModeTrigger />
    </PickerUiModeRoot>

    <PickerUiHistoryRoot>
      <PickerUiHistoryList>
        <PickerUiHistoryListItem />
      </PickerUiHistoryList>
    </PickerUiHistoryRoot>
  </PickerUiRoot>
</template>

API Reference

Root

The base part of the Picker UI.

vue
<PickerUiRoot>
  <!-- Parts go here -->
</PickerUiRoot>
PropDefaultType
as
'div'
AsTag | Component

The element or component this component should render as. Can be overwrite by asChild

asChild
-
boolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Radix-vue composition guide for more details.

modelValue
{ r: 255, g: 0, b: 0 }
RGB | RGBA | HSL | HSLA | HEX | HEXA

The model value of the color picker.


Check useFormatColor for type declarations.

histories
{color: number; alpha: number}[]
{color: number; alpha: number}[]

The model value histories of the color picker.

dir
ltr
ltr | rtl

The reading direction of Color Ui when applicable.
If omitted assumes LTR (left-to-right) reading mode.

acceptedMode
rgb
hsl | rgb | hex

The accepted color mode.

colorFormat
rgb
rgb | hsl | hex

Format modelValue.
If alpha is true, the default value is rgba otherwise rgb

allowedAlpha
false
boolean

When true, allows the user to set the alpha channel.

defaultValue
{ r: 255, g: 0, b: 0 }
RGB | RGBA | HSL | HSLA | HEX | HEXA

The default value of the color picker.


Check useConvertColor for type declarations.

options
{ historyLimit: 8, historyDefault: ...[]}
{ historyLimit?: number, historyDefault?: { color: number[]; alpha: number }[]}

Options for different features.


historyLimit : limit the number of list item history

historyDefault : default history

EmitPayload
update:modelValue
[value: RGB | RGBA | HSL | HSLA | HEX | HEXA]

Event handler called when the color selected change

update:histories
[value: { color: number[]; alpha: number }[]]

Event handler called when the histories change

onChangeComplete
[value: RGB | RGBA | HSL | HSLA | HEX | HEXA]

Event handler called when the color selected change is completed

Slider Main

The main slider to select the color.

vue
<PickerUiSliderMainRoot>
  <PickerUiSliderMainThumb />
</PickerUiSliderMainRoot>

Root

The base of the main slider.

PropDefaultType
as
'div'
AsTag | Component

The element or component this component should render as. Can be overwrite by asChild

asChild
-
boolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Radix-vue composition guide for more details.

disabled
-
boolean

When true, prevents the user from interacting with the slider.

Thumb

The thumb of the slider. Need to be placed inside the SliderMainRoot.

PropDefaultType
as
'span'
AsTag | Component

The element or component this component should render as. Can be overwrite by asChild

asChild
-
boolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Radix-vue composition guide for more details.

Keyboard Interactions

KeyDescription
ArrowRight
Increments valueX.
ArrowLeft
Decrements valueX.
ArrowUp
Increments valueY.
ArrowDown
Decrements valueY.
PageUp
Increases the valueY.
PageDown
Decreases the valueY.
Home
Sets the valueY to its minimum.
End
Sets the valueY to its maximum.
Shift + ArrowRight
Increases valueX.
Shift + ArrowLeft
Decreases valueX.
Shift + ArrowUp
Increases valueY.
Shift + ArrowDown
Decreases valueY.
Shift + PageUp
Decreases the valueX.
Shift + PageDown
Increases the valueX.
Shift + Home
Sets the valueX to its minimum.
Shift + End
Sets the valueX to its maximum.

Render

Used to render the color.

vue
<PickerUiRenderRoot />

Root

The base of the render.

PropDefaultType
as
'div'
AsTag | Component

The element or component this component should render as. Can be overwrite by asChild

asChild
-
boolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Radix-vue composition guide for more details.

hideBackground
false
boolean

Show carret background if alpha is true.

Eye Dropper

Used to pick a color from the screen.

vue
<PickerUiEyeDropperRoot>
  <PickerUiEyeDropperTrigger />
</PickerUiEyeDropperRoot>

Root

The base of the eye dropper.

Trigger

The trigger to pick the color.

PropDefaultType
as
'div'
AsTag | Component

The element or component this component should render as. Can be overwrite by asChild

asChild
-
boolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Radix-vue composition guide for more details.

disabled
-
boolean

When true, prevents the user from interacting with the slider.

Slider Color

The slider to select the color.

vue
<PickerUiSliderColorRoot>
  <PickerUiSliderColorThumb />
</PickerUiSliderColorRoot>

Root

The base of the color slider.

PropDefaultType
as
'div'
AsTag | Component

The element or component this component should render as. Can be overwrite by asChild

asChild
-
boolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Radix-vue composition guide for more details.

orientation
horizontal
horizontal | vertical

The orientation of the slider.

disabled
-
boolean

When true, prevents the user from interacting with the slider.

Thumb

The thumb of the slider. Need to be placed inside the SliderColorRoot.

PropDefaultType
as
'span'
AsTag | Component

The element or component this component should render as. Can be overwrite by asChild

asChild
-
boolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Radix-vue composition guide for more details.

Keyboard Interactions

KeyDescription
ArrowRight
Increments/decrements by the step value depending on orientation.
ArrowLeft
Increments/decrements by the step value depending on orientation.
ArrowUp
Increases the value by the step amount.
ArrowDown
Decreases the value by the step amount.
PageUp
Increases the value by a larger step.
PageDown
Decreases the value by a larger step.
Shift + ArrowUp
Increases the value by a larger step.
Shift + ArrowDown
Decreases the value by a larger step.
Home
Sets the value to its minimum.
End
Sets the value to its maximum.

Slider Alpha

The slider to select the alpha channel.

vue
<PickerUiSliderAlphaRoot>
  <PickerUiSliderAlphaThumb />
</PickerUiSliderAlphaRoot>

Root

The base of the alpha slider.

PropDefaultType
as
'div'
AsTag | Component

The element or component this component should render as. Can be overwrite by asChild

asChild
-
boolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Radix-vue composition guide for more details.

orientation
horizontal
horizontal | vertical

The orientation of the slider.

disabled
-
boolean

When true, prevents the user from interacting with the slider.

hideBackground
false
boolean

Show carret background if alpha is true.

Thumb

The thumb of the slider. Need to be placed inside the SliderAlphaRoot.

PropDefaultType
as
'span'
AsTag | Component

The element or component this component should render as. Can be overwrite by asChild

asChild
-
boolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Radix-vue composition guide for more details.

Keyboard Interactions

KeyDescription
ArrowRight
Increments/decrements by the step value depending on orientation.
ArrowLeft
Increments/decrements by the step value depending on orientation.
ArrowUp
Increases the value by the step amount.
ArrowDown
Decreases the value by the step amount.
PageUp
Increases the value by a larger step.
PageDown
Decreases the value by a larger step.
Shift + ArrowUp
Increases the value by a larger step.
Shift + ArrowDown
Decreases the value by a larger step.
Home
Sets the value to its minimum.
End
Sets the value to its maximum.

Mode

The mode to select the color format.

vue
<PickerUiModeRoot>
  <PickerUiModeContent>
    <PickerUiModeItem>
      <PickerUiModeItemLabel />
      <PickerUiModeItemInput />
    </PickerUiModeItem>
  </PickerUiModeContent>
  <PickerUiModeTrigger />
</PickerUiModeRoot>

Root

The base of the mode.

PropDefaultType
as
'div'
AsTag | Component

The element or component this component should render as. Can be overwrite by asChild

asChild
-
boolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Radix-vue composition guide for more details.

orientation
horizontal
horizontal | vertical

The orientation of the slider.

disabled
-
boolean

When true, prevents the user from interacting with the mode.

Content

The content of the mode.

PropDefaultType
as
'div'
AsTag | Component

The element or component this component should render as. Can be overwrite by asChild

asChild
-
boolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Radix-vue composition guide for more details.

value*
-
hsl | rgb | hex

The mode of the color picker.

Slots (default)Payload
value
hsl | rgb | hex

The value of mode content.

Trigger

The trigger to open the mode.

PropDefaultType
as
'button'
AsTag | Component

The element or component this component should render as. Can be overwrite by asChild

asChild
-
boolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Radix-vue composition guide for more details.

disabled
-
boolean

When true, prevents the user from interacting with the mode.

Slots (default)Payload
mode
hsl | rgb | hex

The current active mode value.

Item

The item of the mode.

PropDefaultType
as
'div'
AsTag | Component

The element or component this component should render as. Can be overwrite by asChild

asChild
-
boolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Radix-vue composition guide for more details.

disabled
-
boolean

When true, prevents the user from interacting with the mode.

value*
-
h | s | l | r | g | b | a | hex

The mode of the color item.

Slots (default)Payload
itemId
string | number

The id of current input/label.

componentField
{ value: string | number; onInput: (event: Event) => void; id: string; }

The modelValue of current input (value and onInput) and the id of field component.

Item Label

The label of the mode item.

PropDefaultType
as
'label'
AsTag | Component

The element or component this component should render as. Can be overwrite by asChild

asChild
-
boolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Radix-vue composition guide for more details.

Item Input

The input of the mode item.

PropDefaultType
as
'input'
AsTag | Component

The element or component this component should render as. Can be overwrite by asChild

asChild
-
boolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Radix-vue composition guide for more details.

disabled
-
boolean

When true, prevents the user from interacting with the input.

History

The history of the selected colors.

vue
<PickerUiHistoryRoot>
  <PickerUiHistoryList>
    <PickerUiHistoryListItem />
  </PickerUiHistoryList>
</PickerUiHistoryRoot>

Root

The base of the history.

PropDefaultType
disabled
-
boolean

When true, prevents the user from interacting with the list item.

List

The content for history.

PropDefaultType
as
'div'
AsTag | Component

The element or component this component should render as. Can be overwrite by asChild

asChild
-
boolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Radix-vue composition guide for more details.

List Item

The item for history.

PropDefaultType
as
'button'
AsTag | Component

The element or component this component should render as. Can be overwrite by asChild

asChild
-
boolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Radix-vue composition guide for more details.

disabled
-
boolean

When true, prevents the user from interacting with the list item.