ColorRing
A circular ring component for adjusting a single color channel along a circular arc.
Preview
#1980e6Source code
<script setup lang="ts">
import "internationalized-color/css";
import {
ColorRingRoot,
ColorRingTrack,
ColorRingGradient,
ColorRingThumb,
useColor,
} from "@urcolor/vue";
const { color, hex } = useColor("hsl(210, 80%, 50%)");
</script>
<template>
<code>{{ hex }}</code>
<ColorRingRoot
v-model="color"
color-space="hsl"
channel="h"
:inner-radius="0.85"
class="relative block size-64"
style="container-type: inline-size"
>
<ColorRingTrack class="relative block size-full">
<ColorRingGradient class="absolute inset-0 block" />
<ColorRingThumb
class="
size-4 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)]
focus-visible:shadow-[0_0_0_1px_rgba(0,0,0,0.3),0_0_0_3px_rgba(66,153,225,0.6)]
"
/>
</ColorRingTrack>
</ColorRingRoot>
</template>Anatomy
<template>
<ColorRingRoot>
<ColorRingTrack>
<ColorRingCheckerboard />
<ColorRingGradient />
<ColorRingThumb />
</ColorRingTrack>
</ColorRingRoot>
</template>Examples
Hue
Hue ring slider for cycling through the color spectrum.
#1980e6Source code
<script setup lang="ts">
import "internationalized-color/css";
import {
ColorRingRoot,
ColorRingTrack,
ColorRingGradient,
ColorRingThumb,
useColor,
} from "@urcolor/vue";
const { color, hex } = useColor("hsl(210, 80%, 50%)");
</script>
<template>
<code>{{ hex }}</code>
<ColorRingRoot
v-model="color"
color-space="hsl"
channel="h"
:inner-radius="0.85"
class="relative block size-64"
style="container-type: inline-size"
>
<ColorRingTrack class="relative block size-full">
<ColorRingGradient class="absolute inset-0 block" />
<ColorRingThumb
class="
size-4 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)]
focus-visible:shadow-[0_0_0_1px_rgba(0,0,0,0.3),0_0_0_3px_rgba(66,153,225,0.6)]
"
/>
</ColorRingTrack>
</ColorRingRoot>
</template>Saturation
Saturation ring slider for adjusting color intensity.
#1980e6Source code
<script setup lang="ts">
import "internationalized-color/css";
import {
ColorRingRoot,
ColorRingTrack,
ColorRingGradient,
ColorRingThumb,
useColor,
} from "@urcolor/vue";
const { color, hex } = useColor("hsl(210, 80%, 50%)");
</script>
<template>
<code>{{ hex }}</code>
<ColorRingRoot
v-model="color"
color-space="hsl"
channel="s"
:inner-radius="0.85"
class="relative block size-64"
style="container-type: inline-size"
>
<ColorRingTrack class="relative block size-full">
<ColorRingGradient class="absolute inset-0 block" />
<ColorRingThumb
class="
size-4 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)]
focus-visible:shadow-[0_0_0_1px_rgba(0,0,0,0.3),0_0_0_3px_rgba(66,153,225,0.6)]
"
/>
</ColorRingTrack>
</ColorRingRoot>
</template>With Alpha
Pass :channel-overrides="false" on ColorRingGradient to reflect the color's alpha channel as opacity on the gradient. Add ColorRingCheckerboard behind the gradient to visualize transparency.
<template>
<ColorRingRoot
:model-value="color"
color-space="hsl"
channel="h"
@update:model-value="onColorUpdate"
>
<ColorRingTrack>
<ColorRingCheckerboard />
<ColorRingGradient :channel-overrides="false" />
<ColorRingThumb />
</ColorRingTrack>
</ColorRingRoot>
</template>API Reference
ColorRingRoot
The root container that manages ring state and color channel binding.
| Prop | Type | Default | Description |
|---|---|---|---|
modelValue | Color | string | null | — | Controlled color value (v-model). |
defaultValue | Color | string | 'hsl(0, 100%, 50%)' | Initial color when uncontrolled. |
colorSpace | string | 'hsl' | Color space mode (e.g. 'hsl', 'oklch'). |
channel | string | Auto | Channel to control (e.g. 'h', 's'). Auto-derived from color space. |
startAngle | number | 0 | Starting angle offset in degrees. |
innerRadius | number | 0.7 | Inner radius ratio (0–1) controlling ring thickness. |
disabled | boolean | false | Disables interaction. |
dir | 'ltr' | 'rtl' | — | Reading direction. |
name | string | — | Hidden input name for form submission. |
required | boolean | false | Marks as required for form submission. |
| Event | Payload | Description |
|---|---|---|
update:modelValue | Color | undefined | Emitted when color changes. |
valueCommit | Color | Emitted when interaction ends. |
ColorRingTrack
The track container that holds the gradient, checkerboard, and thumb.
ColorRingGradient
Renders a ring gradient canvas for the track. Automatically samples the gradient from the root's color space and channel configuration.
| Prop | Type | Default | Description |
|---|---|---|---|
channelOverrides | Record<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. |
ColorRingCheckerboard
Renders a checkerboard pattern behind the gradient to visualize alpha transparency. Place it inside ColorRingTrack before ColorRingGradient.
ColorRingThumb
The draggable thumb element positioned along the ring arc.
Accessibility
ColorRing provides a circular slider interface for adjusting a single color channel with full keyboard support.
ARIA Labels
| Attribute | Description |
|---|---|
aria-label | Labels the slider with the controlled channel name. |
role="slider" | Applied to the thumb element for screen reader recognition. |
aria-valuemin / aria-valuemax | Defines the channel's value range. |
aria-valuenow | Current value of the channel. |
Keyboard Navigation
| Key | Action |
|---|---|
| Arrow Right / Arrow Up | Increase by one step |
| Arrow Left / Arrow Down | Decrease by one step |
| Shift + Arrow | Move by 10 steps |
| Page Up | Increase by 10 steps |
| Page Down | Decrease by 10 steps |
| Home | Move to minimum |
| End | Move to maximum |