Marble UI
← Components

Color Wheel

Preview: Wheel

Circular hue picker (React Aria ColorWheel): drag, or use arrow keys.

Import

import { ColorWheel } from '@marbleui/ui'

Props

<ColorWheel>

PropTypeDefaultDescription
innerRadiusnumber74
outerRadiusnumber100

Also accepts React Aria props (87).

Accessibility

Keyboard interaction, focus management and ARIA semantics come from the underlying primitives: React Aria ColorWheel · React Aria ColorWheelTrack. Follow the primitive's docs for the full keyboard map.

Usage notes

ColorWheel is a ring for choosing hue only; saturation and brightness stay as they are. Put a ColorArea inside it for a full editor, or use ColorPicker for a popover.

import { parseColor } from 'react-aria-components'
const [color, setColor] = useState(parseColor('hsl(210, 90%, 55%)'))
<ColorWheel aria-label="Accent hue" value={color} onChange={setColor} onChangeEnd={saveTheme} />
  • Uncontrolled: defaultValue (red if omitted). Controlled: value + onChange, which fires while dragging; onChangeEnd fires once on release. Values can be a Color or a color string.
  • outerRadius (default 100) and innerRadius (default 74) are in pixels, so the default wheel is 200px wide with a 148px hole.
  • Arrow keys change the hue by 1°, Shift+arrow or Page Up/Down by 15°. Screen readers hear the angle and a color name. The default name is “Hue”; pass aria-label to say what the hue is for.
Example source · show
import { useState } from 'react'
import { parseColor } from 'react-aria-components'
import { ColorArea } from '../color-area'
import { ColorWheel } from './color-wheel'

function Wheel() {
  const [c, setC] = useState(parseColor('hsl(210, 90%, 55%)'))
  return <div className="flex items-center gap-6"><ColorWheel value={c} onChange={setC} /><div className="flex flex-col gap-2"><span className="size-16 rounded-xl border border-border" style={{ background: c.toString('css') }} /><span className="font-mono text-xs text-fg-muted">{c.toString('hex')}</span></div></div>
}
function WithArea() {
  const [c, setC] = useState(parseColor('hsb(320, 70%, 80%)'))
  return (
    // Stack in one grid cell: React Aria sets position: relative inline on the wheel, so absolute positioning doesn't take.
    <div className="grid place-items-center">
      <ColorWheel value={c} onChange={setC} className="[grid-area:1/1]" />
      <ColorArea value={c} onChange={setC} size="sm" className="[grid-area:1/1] !size-[100px]" />
    </div>
  )
}
export const styles = { Wheel, 'Wheel + area': WithArea }

Source: packages/ui/src/color-wheel/color-wheel.tsx

Catalog

Category
color
Priority
Extra
Primitive
react-aria
React Aria
ColorWheel