Skip to content

ColorRing

A circular ring component for adjusting a single color channel along a circular arc.

Preview

Source code
tsx
import "internationalized-color/css";
import { ColorRing, useColor } from "@urcolor/react";

export default function ColorRingHue() {
  const { color, setColor, hex } = useColor("hsl(210, 80%, 50%)");

  return (
    <>
      <code>{hex}</code>
      <ColorRing.Root
        value={color}
        onValueChange={setColor}
        colorSpace="hsl"
        channel="h"
        innerRadius={0.85}
        className="relative block size-64"
        style={{ containerType: "inline-size" }}
      >
        <ColorRing.Track className="relative block size-full">
          <ColorRing.Gradient className="absolute inset-0 block" />
          <ColorRing.Thumb
            className="
              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)]
            "
          />
        </ColorRing.Track>
      </ColorRing.Root>
    </>
  );
}

Anatomy

tsx
<ColorRing.Root>
  <ColorRing.Track>
    <ColorRing.Checkerboard />
    <ColorRing.Gradient />
    <ColorRing.Thumb />
  </ColorRing.Track>
</ColorRing.Root>

Examples

Hue

Hue ring slider for cycling through the color spectrum.

Source code
tsx
import "internationalized-color/css";
import { ColorRing, useColor } from "@urcolor/react";

export default function ColorRingHue() {
  const { color, setColor, hex } = useColor("hsl(210, 80%, 50%)");

  return (
    <>
      <code>{hex}</code>
      <ColorRing.Root
        value={color}
        onValueChange={setColor}
        colorSpace="hsl"
        channel="h"
        innerRadius={0.85}
        className="relative block size-64"
        style={{ containerType: "inline-size" }}
      >
        <ColorRing.Track className="relative block size-full">
          <ColorRing.Gradient className="absolute inset-0 block" />
          <ColorRing.Thumb
            className="
              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)]
            "
          />
        </ColorRing.Track>
      </ColorRing.Root>
    </>
  );
}

Saturation

Saturation ring slider for adjusting color intensity.

Source code
tsx
import "internationalized-color/css";
import { ColorRing, useColor } from "@urcolor/react";

export default function ColorRingSaturation() {
  const { color, setColor, hex } = useColor("hsl(210, 80%, 50%)");

  return (
    <>
      <code>{hex}</code>
      <ColorRing.Root
        value={color}
        onValueChange={setColor}
        colorSpace="hsl"
        channel="s"
        innerRadius={0.85}
        className="relative block size-64"
        style={{ containerType: "inline-size" }}
      >
        <ColorRing.Track className="relative block size-full">
          <ColorRing.Gradient className="absolute inset-0 block" />
          <ColorRing.Thumb
            className="
              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)]
            "
          />
        </ColorRing.Track>
      </ColorRing.Root>
    </>
  );
}

API Reference

ColorRing.Root

The root container that manages ring state and color channel binding.

PropTypeDefaultDescription
valueColor | string | nullControlled color value.
defaultValueColor | string'hsl(0, 100%, 50%)'Initial color when uncontrolled.
colorSpacestring'hsl'Color space mode (e.g. 'hsl', 'oklch').
channelstringAutoChannel to control. Auto-derived from color space.
startAnglenumber0Starting angle offset in degrees.
innerRadiusnumber0.7Inner radius ratio (0–1) controlling ring thickness.
disabledbooleanfalseDisables interaction.
onValueChange(color: Color) => voidCalled when color changes.
onValueCommit(color: Color) => voidCalled when interaction ends.

ColorRing.Track

The track container that holds the gradient, checkerboard, and thumb.

ColorRing.Gradient

Renders a ring gradient canvas for the track.

PropTypeDefaultDescription
channelOverridesRecord<string, number> | false{ alpha: 1 }Lock specific channels to fixed values in the gradient.

ColorRing.Checkerboard

Renders a checkerboard pattern behind the gradient to visualize alpha transparency.

ColorRing.Thumb

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.

Keyboard Navigation

KeyAction
Arrow Right / Arrow UpIncrease by one step
Arrow Left / Arrow DownDecrease by one step
Shift + ArrowMove by 10 steps
Page UpIncrease by 10 steps
Page DownDecrease by 10 steps
HomeMove to minimum
EndMove to maximum