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.
import { ColorArea, ColorAreaThumb } from "ropav";<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
<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
tabindexandaria-hiddenso 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-valuetextfollows 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-labelnames the area, and the words "color picker" are appended to whatever you give it.
API
ColorArea
| Prop | Type | Default | Description |
|---|---|---|---|
ariaDescribedby | string | — | Ids of the elements that describe the area. |
ariaLabel | string | — | Accessible name. The words "color picker" are appended to it. |
ariaLabelledby | string | — | 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. |
defaultValue | string | 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. |
form | string | — | id of the form to submit with, for an area rendered outside it. |
id | string | — | Id of the area, and the stem both hidden inputs' ids grow from. |
isDisabled | boolean | — | |
showDots | boolean | false
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. |
value | string | 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. |
xName | string | — | 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. |
yName | string | — | Name the vertical channel is submitted under. |
The default slot receives:
| Slot prop | Type |
|---|---|
color | Color |
isDisabled | boolean |
| Event | Payload |
|---|---|
change | Color |
changeEnd | Color |
update:value | Color |
ColorAreaThumb
The default slot receives:
| Slot prop | Type |
|---|---|
color | Color |
isDisabled | boolean |
isDragging | boolean |
isFocused | boolean |
isFocusVisible | boolean |
isHovered | boolean |