ColorArea

A 2D color picker that allows users to select colors from a gradient area

Usage

<script setup lang="ts">
import { ColorArea } from '@hareui/vue'
</script>
<script setup lang="ts">import { ColorArea } from '@hareui/vue'</script><template>  <ColorArea default-value="rgb(116, 52, 255)" /></template>

Anatomy

ColorArea renders the gradient area with its draggable thumb built in (HeroUI's ColorArea.Thumb child). Style the parts with class and ui.

<template>
  <ColorArea />
</template>
ui keydata-slotElement
basecolor-area<div role="application"> gradient area
thumbcolor-area-thumb<div role="slider"> thumb

Examples

With Dots

<script setup lang="ts">import { ColorArea } from '@hareui/vue'</script><template>  <ColorArea show-dots default-value="hsl(200, 100%, 50%)" /></template>

Color Space & Channels

Use color-space to set the color space (RGB, HSL, HSB) and x-channel / y-channel to choose which channels are shown on each axis.

Color Space
X Axis
Y Axis
hsb(219, 58%, 93%)
<script setup lang="ts">import type { ColorChannel, ColorSpace, ListBoxItem, SelectValue } from '@hareui/vue'import { ColorArea, colorToString, parseColor, Select } from '@hareui/vue'import { computed, ref } from 'vue'const colorSpaces: ListBoxItem[] = [  { value: 'rgb', label: 'RGB' },  { value: 'hsl', label: 'HSL' },  { value: 'hsb', label: 'HSB' },]const channelsBySpace: Record<ColorSpace, Array<{ value: ColorChannel, label: string }>> = {  hsb: [    { value: 'hue', label: 'Hue' },    { value: 'saturation', label: 'Saturation' },    { value: 'brightness', label: 'Brightness' },  ],  hsl: [    { value: 'hue', label: 'Hue' },    { value: 'saturation', label: 'Saturation' },    { value: 'lightness', label: 'Lightness' },  ],  rgb: [    { value: 'red', label: 'Red' },    { value: 'green', label: 'Green' },    { value: 'blue', label: 'Blue' },  ],}const colorSpace = ref<ColorSpace>('hsb')const color = ref(parseColor('hsb(219, 58%, 93%)'))const xChannel = ref<ColorChannel>('saturation')const yChannel = ref<ColorChannel>('brightness')function onSpaceChange(space: SelectValue | undefined) {  if (!space || typeof space !== 'string')    return  colorSpace.value = space as ColorSpace  // Reset the channels to sensible defaults for the new colour space  if (space === 'rgb') {    xChannel.value = 'blue'    yChannel.value = 'green'  }  else if (space === 'hsl') {    xChannel.value = 'saturation'    yChannel.value = 'lightness'  }  else {    xChannel.value = 'saturation'    yChannel.value = 'brightness'  }}// A channel can't be on both axes, so each axis hides the other's channelconst xChannelOptions = computed(() => channelsBySpace[colorSpace.value].filter(c => c.value !== yChannel.value))const yChannelOptions = computed(() => channelsBySpace[colorSpace.value].filter(c => c.value !== xChannel.value))</script><template>  <div class="flex flex-col items-center gap-6">    <div class="flex gap-4">      <Select class="w-32" label="Color Space" :model-value="colorSpace" :items="colorSpaces" @update:model-value="onSpaceChange" />      <Select v-model="xChannel" class="w-36" label="X Axis" :items="xChannelOptions" />      <Select v-model="yChannel" class="w-36" label="Y Axis" :items="yChannelOptions" />    </div>    <ColorArea      v-model="color"      :color-space="colorSpace"      :x-channel="xChannel"      :y-channel="yChannel"    />    <div class="flex items-center gap-3">      <div        class="size-8 rounded-md border border-default"        :style="{ backgroundColor: colorToString(color, 'rgb') }"      />      <code class="rounded bg-default/50 px-2 py-1 text-sm">        {{ colorToString(color, colorSpace) }}      </code>    </div>  </div></template>

Disabled

<script setup lang="ts">import { ColorArea } from '@hareui/vue'</script><template>  <ColorArea disabled default-value="hsl(200, 100%, 50%)" /></template>

Controlled

Bind the value with v-model. The committed value is always a Color object; use colorToString(color, 'hex') to read it as a string. Inside a ColorPicker the area reads and writes the picker's colour instead.

Current color: #9b80ff

<script setup lang="ts">import { ColorArea, ColorSwatch, colorToString, parseColor } from '@hareui/vue'import { ref } from 'vue'const color = ref(parseColor('#9B80FF'))</script><template>  <div class="flex flex-col gap-4">    <ColorArea v-model="color" color-space="rgb" x-channel="red" y-channel="green" />    <div class="flex w-[300px] items-center gap-3">      <ColorSwatch :color="color" size="md" />      <p class="text-sm text-muted">        Current color:        <span class="font-medium">{{ color ? colorToString(color, 'hex') : '(empty)' }}</span>      </p>    </div>  </div></template>

Render Function

HeroUI's render prop replaces the root element. In Vue, attributes you pass to ColorArea fall through to the root element.

<script setup lang="ts">import { ColorArea } from '@hareui/vue'</script><template>  <!-- Attributes fall through to the root element (HeroUI's `render` prop) -->  <ColorArea default-value="rgb(116, 52, 255)" data-custom="slider" /></template>

Customization

Tailwind CSS

<script setup lang="ts">import { ColorArea } from '@hareui/vue'</script><template>  <ColorArea    class="size-44 rounded-3xl"    :ui="{ thumb: 'size-5 rounded-full border-4 border-white' }"    default-value="rgb(116, 52, 255)"  /></template>

Global Configuration

app.use(createHareUI({
  ui: { colorArea: { slots: { base: 'rounded-3xl', thumb: 'size-5 border-4' } } },
}))

Styling Reference

Slots

  • base → [data-slot="color-area"] – gradient area with inner shadow
  • thumb → [data-slot="color-area-thumb"] – draggable thumb

Variants

  • showDots – adds a dot grid overlay for precision picking

Interactive States

  • Disabled: [data-disabled] on the area and thumb
  • Focus Visible: :focus-visible on the thumb
  • Dragging: [data-dragging="true"] on the thumb

API Reference

Props

PropTypeDefaultDescription
modelValuestring | Color-The colour value (controlled), as a hex/CSS colour string or a Color object. Use with v-model. When omitted and used inside a ColorPicker, falls back to its current colour.
defaultValuestring | Color-The default colour when uncontrolled.
colorSpaceColorSpace-The colour space the channels are read from. Defaults to the colour's own space.
xChannelColorChannel-Colour channel for the horizontal (x) axis. Defaults to the first channel of the colour space that isn't yChannel (hue for HSL/HSB, red for RGB), as in React Aria.
yChannelColorChannel-Colour channel for the vertical (y) axis. Defaults to the first channel of the colour space that isn't the x channel (saturation for HSL/HSB, green for RGB), as in React Aria.
disabledboolean-Whether the colour area is disabled.
showDotsboolean-Whether to show the dot grid overlay for precision picking.
xNamestring-The name of the x channel's hidden input, for form submission.
yNamestring-The name of the y channel's hidden input, for form submission.
uiComponentSlots<{ slots: { base: string[]; thumb: string[]; }; variants: { showDots: { false: {}; true: { base: string[]; }; }; }; defaultVariants: { showDots: boolean; }; }>-Per-slot class overrides.

Emits

EventPayloadDescription
update:modelValue[value: string | Color | undefined]-
change[value: Color]-
changeEnd[value: Color]-

Accessibility

  • The area is role="application" and the thumb a role="slider" with an aria-valuetext describing both channels
  • Keyboard: arrow keys move the thumb on both axes, PageUp/PageDown/Home/End take larger steps

On this page

No Headings