Skip to content

ColorArea ​

A colour area is the square in a colour picker: two channels laid out on two axes with one thumb moving across both. The third channel is not here — it belongs to a slider beside it, which is why an area is almost always part of a ColorPicker rather than a control on its own.

ts
import { ColorArea, ColorAreaThumb } from "ropav";
template
<ColorArea aria-label="Brand" class="w-64" default-value="hsl(200, 100%, 50%)">
  <ColorAreaThumb />
</ColorArea>

Pressing anywhere on the square jumps the thumb there and carries straight on as a drag, so picking a colour is one gesture rather than a press followed by a grab.

Choosing the channels ​

x-channel and y-channel have to belong to the area's colour space, and the space defaults to whichever one the value is already in. So the value decides the square: hsb(30, 100%, 100%) gives you saturation × brightness, and an rgb value gives you red × green.

Saturation × brightness

Red × green

color-area-channels.vue
vue
<script setup lang="ts">
import { ColorArea, ColorAreaThumb } from "ropav";
</script>

<template>
  <div class="stack">
    <p class="note">Saturation × brightness</p>
    <ColorArea
      aria-label="Saturation and brightness"
      class="area"
      default-value="hsb(30, 100%, 100%)"
    >
      <ColorAreaThumb />
    </ColorArea>
  </div>

  <div class="stack">
    <p class="note">Red × green</p>
    <ColorArea
      aria-label="Red and green"
      class="area"
      default-value="rgb(255, 100, 50)"
      x-channel="red"
      y-channel="green"
    >
      <ColorAreaThumb />
    </ColorArea>
  </div>
</template>

<style scoped>
.stack {
  display: flex;
  flex-direction: column;
  gap: calc(var(--rp-spacing) * 2);
}

.stack .note {
  color: var(--rp-muted);
  font-size: var(--rp-text-sm);
  line-height: var(--rp-text-sm--line-height);
}

.area {
  width: calc(var(--rp-spacing) * 56);
}
</style>

An area with no value at all falls back to white, which is an rgb colour — so it is red × green, not the hue square the name might suggest. Give it a default-value in the space you mean.

Accessibility ​

  • Under the square are two hidden range inputs, one per channel. They juggle tabindex and aria-hidden so assistive technology lists one two-dimensional control rather than two sliders — and then reveal both as soon as the keyboard is used, so each channel can be read on its own.
  • aria-valuetext follows from that. Before the keyboard is used a reader hears all three channels; after it, only the one that moved. Both go back to the start when focus leaves.
  • The arrow keys move one step along their axis. Home and End page along x and PageUp / PageDown page along y — which is not what those keys mean on a slider, where they jump to the ends.
  • aria-label names the area, and the words "color picker" are appended to whatever you give it.

API ​

ColorArea

PropTypeDefaultDescription
ariaDescribedbystring—Ids of the elements that describe the area.
ariaLabelstring—Accessible name. The words "color picker" are appended to it.
ariaLabelledbystring—Ids of the elements that name the area.
colorSpace"hsb" | "hsl" | "rgb"—The space the area works in; xChannel and yChannel have to belong to it. Defaults to the space the value itself is in.
defaultValuestring | Color—Colour used while the area is uncontrolled. Absent means white — which is an rgb colour, so an area with no value at all is red × green rather than the hue square the name suggests.
formstring—id of the form to submit with, for an area rendered outside it.
idstring—Id of the area, and the stem both hidden inputs' ids grow from.
isDisabledboolean—
showDotsbooleanfalse Declared as a plain `boolean` rather than as `ColorAreaVariants["showDots"]`: Vue's compiler only casts a bare `show-dots` attribute to `true` for a prop it can see is Boolean, and an indexed access into an imported type is not something it can resolve. Written the other way the attribute arrives as `""`, which no variant matches, and the dots silently never appear.Overlays a dot pattern, purely decorative.
valuestring | Color—Current colour. A string is parsed.
xChannel"alpha" | "blue" | "brightness" | "green" | "hue" | "lightness" | "red" | "saturation"—Channel on the horizontal axis. Defaults to the first channel of the space.
xNamestring—Name the horizontal channel is submitted under.
yChannel"alpha" | "blue" | "brightness" | "green" | "hue" | "lightness" | "red" | "saturation"—Channel on the vertical axis. Defaults to the next channel of the space.
yNamestring—Name the vertical channel is submitted under.

The default slot receives:

Slot propType
colorColor
isDisabledboolean
EventPayload
changeColor
changeEndColor
update:valueColor

ColorAreaThumb

The default slot receives:

Slot propType
colorColor
isDisabledboolean
isDraggingboolean
isFocusedboolean
isFocusVisibleboolean
isHoveredboolean