Skip to content

ColorArea

A 2D slider component for selecting values across two axes, ideal for color picking (e.g., saturation and lightness).

Preview

Source code
vue
<script setup lang="ts">
import "internationalized-color/css";
import {
  ColorAreaRoot,
  ColorAreaTrack,
  ColorAreaGradient,
  ColorAreaThumb,
  ColorAreaThumbX,
  ColorAreaThumbY,
  useColor,
} from "@urcolor/vue";

const { color } = useColor("hsl(210, 80%, 50%)");
</script>

<template>
  <ColorAreaRoot
    v-model="color"
    color-space="hsl"
    channel-x="h"
    channel-y="s"
    as="div"
    class="block"
    aria-label="HSL color area"
  >
    <ColorAreaTrack
      as="div"
      class="
        relative h-[200px] w-full cursor-crosshair touch-none overflow-clip
        rounded-lg
      "
    >
      <ColorAreaGradient
        as="div"
        class="absolute inset-0"
      />
      <ColorAreaThumb
        as="div"
        class="
          absolute size-5 transform-(--reka-slider-area-thumb-transform)
          rounded-full border-2 border-white
          shadow-[0_0_0_1px_rgba(0,0,0,0.3),0_2px_4px_rgba(0,0,0,0.3)]
        "
      >
        <ColorAreaThumbX class="outline-none" />
        <ColorAreaThumbY class="outline-none" />
      </ColorAreaThumb>
    </ColorAreaTrack>
  </ColorAreaRoot>
</template>

Anatomy

vue
<template>
  <ColorAreaRoot>
    <ColorAreaTrack>
      <ColorAreaCheckerboard />
      <ColorAreaGradient />
      <ColorAreaThumb>
        <ColorAreaThumbX />
        <ColorAreaThumbY />
      </ColorAreaThumb>
    </ColorAreaTrack>
  </ColorAreaRoot>
</template>

Examples

HSL

HSL color area with Hue on X and Saturation on Y.

Source code
vue
<script setup lang="ts">
import "internationalized-color/css";
import {
  ColorAreaRoot,
  ColorAreaTrack,
  ColorAreaGradient,
  ColorAreaThumb,
  ColorAreaThumbX,
  ColorAreaThumbY,
  useColor,
} from "@urcolor/vue";

const { color } = useColor("hsl(210, 80%, 50%)");
</script>

<template>
  <ColorAreaRoot
    v-model="color"
    color-space="hsl"
    channel-x="h"
    channel-y="s"
    as="div"
    class="block"
    aria-label="HSL color area"
  >
    <ColorAreaTrack
      as="div"
      class="
        relative h-[200px] w-full cursor-crosshair touch-none overflow-clip
        rounded-lg
      "
    >
      <ColorAreaGradient
        as="div"
        class="absolute inset-0"
      />
      <ColorAreaThumb
        as="div"
        class="
          absolute size-5 transform-(--reka-slider-area-thumb-transform)
          rounded-full border-2 border-white
          shadow-[0_0_0_1px_rgba(0,0,0,0.3),0_2px_4px_rgba(0,0,0,0.3)]
        "
      >
        <ColorAreaThumbX class="outline-none" />
        <ColorAreaThumbY class="outline-none" />
      </ColorAreaThumb>
    </ColorAreaTrack>
  </ColorAreaRoot>
</template>

OKLCh

OKLCh color area with Chroma on X and Lightness on Y.

Source code
vue
<script setup lang="ts">
import "internationalized-color/css";
import {
  ColorAreaRoot,
  ColorAreaTrack,
  ColorAreaGradient,
  ColorAreaThumb,
  ColorAreaThumbX,
  ColorAreaThumbY,
  useColor,
} from "@urcolor/vue";

const { color } = useColor("hsl(210, 80%, 50%)");
</script>

<template>
  <ColorAreaRoot
    v-model="color"
    color-space="oklch"
    channel-x="c"
    channel-y="l"
    as="div"
    class="block"
    aria-label="OKLCh color area"
  >
    <ColorAreaTrack
      as="div"
      class="
        relative h-[200px] w-full cursor-crosshair touch-none overflow-clip
        rounded-lg
      "
    >
      <ColorAreaGradient
        as="div"
        class="absolute inset-0"
      />
      <ColorAreaThumb
        as="div"
        class="
          absolute size-5 transform-(--reka-slider-area-thumb-transform)
          rounded-full border-2 border-white
          shadow-[0_0_0_1px_rgba(0,0,0,0.3),0_2px_4px_rgba(0,0,0,0.3)]
        "
      >
        <ColorAreaThumbX class="outline-none" />
        <ColorAreaThumbY class="outline-none" />
      </ColorAreaThumb>
    </ColorAreaTrack>
  </ColorAreaRoot>
</template>

With Alpha

Pass :channel-overrides="false" on ColorAreaGradient to reflect the color's alpha channel as opacity on the gradient. Add ColorAreaCheckerboard behind the gradient to visualize transparency.

vue
<template>
  <ColorAreaRoot
    :model-value="color"
    color-space="hsl"
    channel-x="s"
    channel-y="l"
    @update:model-value="onColorUpdate"
  >
    <ColorAreaTrack>
      <ColorAreaCheckerboard />
      <ColorAreaGradient :channel-overrides="false" />
      <ColorAreaThumb>
        <ColorAreaThumbX />
        <ColorAreaThumbY />
      </ColorAreaThumb>
    </ColorAreaTrack>
  </ColorAreaRoot>
</template>

API Reference

ColorAreaRoot

The root container that manages slider state.

PropTypeDefaultDescription
modelValueColor | string | nullControlled color value (v-model).
defaultValueColor | string'hsl(0, 100%, 50%)'Initial color when uncontrolled.
colorSpacestring'hsl'Color space mode (e.g. 'hsl', 'oklch').
channelXstringAutoChannel for the X axis (e.g. 's', 'alpha'). Auto-derived from color space.
channelYstringAutoChannel for the Y axis (e.g. 'l', 'alpha'). Auto-derived from color space.
disabledbooleanfalseDisables interaction.
dir'ltr' | 'rtl'Reading direction.
invertedXbooleanfalseInvert X axis.
invertedYbooleanfalseInvert Y axis.
thumbAlignment'contain' | 'overflow''overflow'How thumb is positioned relative to track bounds.
namestringHidden input name for form submission.
requiredbooleanfalseMarks as required for form submission.
EventPayloadDescription
update:modelValueColor | undefinedEmitted when color changes.
valueCommitColorEmitted when interaction ends.

ColorAreaTrack

The track area that contains thumbs and receives pointer events.

ColorAreaGradient

Renders a 2D gradient canvas for the color area. Automatically samples the gradient from the root's color space and channel configuration.

PropTypeDefaultDescription
topLeftstringOverride: color for the top-left corner.
topRightstringOverride: color for the top-right corner.
bottomLeftstringOverride: color for the bottom-left corner.
bottomRightstringOverride: color for the bottom-right corner.
interpolationSpacestringColor space for perceptual interpolation (e.g. 'oklch').
channelOverridesRecord<string, number> | false{ alpha: 1 }Lock specific channels to fixed values in the gradient. Set to false to reflect all channels from current color including alpha. E.g. { s: 1, v: 1, alpha: 1 } for an immutable hue gradient in HSV.

ColorAreaCheckerboard

Renders a checkerboard pattern behind the gradient to visualize alpha transparency. Place it inside ColorAreaTrack before ColorAreaGradient.

ColorAreaThumb

Wrapper for the thumb indicator. Position is set automatically via CSS custom properties.

ColorAreaThumbX / ColorAreaThumbY

Individual axis thumb elements. Both are required inside ColorAreaThumb for keyboard navigation to work on both axes.

Accessibility

ColorArea provides a 2D slider interface with two independently focusable thumb elements for keyboard access to both axes.

ARIA Labels

AttributeDescription
aria-labelLabels the root element with the color area's purpose.
role="slider"Applied to each thumb element (ThumbX, ThumbY) for screen reader recognition.
aria-valuemin / aria-valuemaxDefines the range for each axis channel.
aria-valuenowCurrent value of the focused channel.

Keyboard Navigation

KeyAction
Arrow keysMove by one step
Shift + ArrowMove by 10 steps
Home / EndMove to X-axis min/max
Page Up / Page DownMove to Y-axis min/max