Skip to content

ColorPicker ​

A colour picker holds one colour and opens a popover to change it. What it mostly does is share: every colour component underneath reads the picker's value and writes back to it, so a swatch, an area, a slider and a field inside one picker are all looking at the same colour without a single v-model between them.

ts
import { ColorPicker, ColorPickerPopover, ColorPickerTrigger } from "ropav";
color-picker-basic.vue
vue
<script setup lang="ts">
import {
  ColorArea,
  ColorAreaThumb,
  ColorPicker,
  ColorPickerPopover,
  ColorPickerTrigger,
  ColorSlider,
  ColorSliderThumb,
  ColorSliderTrack,
  ColorSwatch,
  Label,
} from "ropav";
</script>

<template>
  <ColorPicker default-value="#0485f7">
    <ColorPickerTrigger>
      <ColorSwatch size="lg" />
      <Label>Brand colour</Label>
    </ColorPickerTrigger>

    <ColorPickerPopover>
      <ColorArea
        aria-label="Saturation and brightness"
        class="picker"
        color-space="hsb"
        x-channel="saturation"
        y-channel="brightness"
      >
        <ColorAreaThumb />
      </ColorArea>

      <ColorSlider channel="hue" class="channel" color-space="hsb">
        <ColorSliderTrack>
          <ColorSliderThumb />
        </ColorSliderTrack>
      </ColorSlider>
    </ColorPickerPopover>
  </ColorPicker>
</template>

<style scoped>
.picker {
  max-width: 100%;
}

.channel {
  padding-inline: var(--rp-spacing);
}
</style>

The trigger is a button showing a ColorSwatch with no color of its own — it takes the picker's. Inside the popover, ColorArea covers two channels and a ColorSlider covers the third; ColorSwatchPicker for presets and ColorField for a typed hex value are the other two pieces.

Holding the colour ​

default-value starts an uncontrolled picker; value with a change listener, or v-model:value, hands the colour to the caller. change carries a parsed Color, so color.toString("hex") is how you get back to a string.

The popover's open state works the same way: default-open, or is-open with open-change.

Accessibility ​

  • The popover is a dialog, so Esc closes it and focus returns to the trigger.
  • Every control inside names itself. The area and the sliders describe the channel they move and the colour they arrive at, which is what makes a colour reachable without seeing it — and it is why the popover should hold real colour controls rather than a canvas you drew yourself.
  • The trigger needs to say what colour is being picked. The swatch announces the colour; the label beside it is what says which colour on the page it belongs to.

API ​

ColorPicker

PropTypeDefaultDescription
defaultOpenboolean—Whether the popover starts open.
defaultValuestring | Color"#000000"Colour the picker starts on while it is uncontrolled.
isOpenboolean—Controlled open state.
valuestring | Color—Controlled colour. A string is parsed.

The default slot receives:

Slot propType
colorColor
EventPayload
changeColor
openChangeboolean
update:isOpenboolean
update:valueColor

ColorPickerPopover

PropTypeDefaultDescription
containerPaddingnumber—
crossOffsetnumber—
isKeyboardDismissDisabledboolean—
offsetnumber—
placement"bottom" | "bottom end" | "bottom left" | "bottom right" | "bottom start" | "end" | "end bottom" | "end top" | "left" | "left bottom" | "left top" | "right" | "right bottom" | "right top" | "start" | "start bottom" | "start top" | "top" | "top end" | "top left" | "top right" | "top start""bottom left"
shouldFlipboolean—

Slots: default.

ColorPickerTrigger

PropTypeDefaultDescription
type"button" | "reset" | "submit""button"

Slots: default.