Mosmox UI
Current version
GitHubnpmjs.com
Forms & Inputs

Color Picker

Accessible color selection with multiple color formats, palettes, tokens, eyedropper, contrast checks, and controlled commit flow.

ColorPicker provides a compact trigger or an always-visible inline editor. It combines a saturation/brightness area, hue and opacity sliders, text input, presets, recent colors, design-token swatches, an optional browser eyedropper, and contrast information.

Basic usage

import { ColorPicker } from '@mosmox/ui';

<ColorPicker label="Brand color" defaultValue="#003231" />

The default picker opens from a trigger. Select a point in the color area, adjust hue or opacity, or enter a value directly.

Controlled usage and commit lifecycle

Use value and onChange when the parent owns the live value. onChange is emitted for every valid interaction. Use onCommit for persistence and onCancel for reverting an open edit session.

const [color, setColor] = useState('#003231');

<ColorPicker
  value={color}
  onChange={setColor}
  onCommit={(next) => saveThemeColor(next)}
  onCancel={() => console.log('Color edit cancelled')}
  onInvalid={(raw) => console.warn('Invalid color:', raw)}
  aria-label="Theme color"
/>

onCommit also records the value in the internal recent-color list. A valid text value is committed on Enter or blur. Invalid text remains visible, receives aria-invalid, shows invalidMessage, and invokes onInvalid.

Supported formats

format controls the string emitted by onChange and onCommit. Input parsing accepts HEX (#rgb, #rgba, #rrggbb, #rrggbbaa), RGB/RGBA, HSL/HSLA, and HSB/HSV notation.

<ColorPicker format="hex" defaultValue="#12b76a" />
<ColorPicker format="hex8" defaultValue="#2e90facc" showAlpha />
<ColorPicker format="rgb" defaultValue="rgb(46, 144, 250)" />
<ColorPicker format="rgba" defaultValue="rgba(46, 144, 250, 0.7)" showAlpha />
<ColorPicker format="hsl" defaultValue="hsl(210, 82%, 58%)" />
<ColorPicker format="hsla" defaultValue="hsla(210, 82%, 58%, 0.7)" showAlpha />
<ColorPicker format="hsb" defaultValue="hsb(210, 82%, 98%)" />
<ColorPicker format="hsva" defaultValue="hsva(210, 82%, 98%, 0.7)" showAlpha />
FormatExample outputAlpha
hex#2e90fano
hex8#2e90facchexadecimal channel
rgbrgb(46, 144, 250)no
rgbargba(46, 144, 250, 0.8)decimal or percentage
hslhsl(210, 82%, 58%)no
hslahsla(210, 82%, 58%, 0.8)decimal or percentage
hsb / hsvhsb(210, 82%, 98%)no
hsba / hsvahsba(210, 82%, 98%, 0.8)decimal or percentage

Use alphaFormat="percentage" when the alpha channel should be emitted as 80% instead of 0.8. Opaque formats intentionally omit alpha even when showAlpha is enabled.

Transparency and validation

Set allowTransparent to let users select the special transparent value. This is useful for overlays, borders, and optional theme values.

<ColorPicker
  allowTransparent
  defaultValue="transparent"
  onInvalid={(value) => announce(`Invalid value ${value}`)}
  invalidMessage="Use a HEX, RGB, HSL, HSV, or transparent value."
/>

Palettes, presets, recent colors, and tokens

swatches is the regular palette. presets is rendered before it and can contain labeled objects. Recent colors are enabled with showRecent; double-clicking a recent swatch invokes onSwatchRemove. allowCustomSwatch exposes an action that sends the current value to onSwatchAdd so the application can persist its own palette.

<ColorPicker
  defaultValue="#12b76a"
  swatchShape="square"
  swatchSize={28}
  showSwatchLabels
  presets={[
    { value: '#003231', label: 'Brand dark' },
    { value: '#12b76a', label: 'Success' },
  ]}
  recentColors={['#f79009', '#7f56d9']}
  showRecent
  allowCustomSwatch
  onSwatchAdd={(value) => saveRecentColor(value)}
  onSwatchRemove={(value) => removeRecentColor(value)}
/>

tokenOptions resolves theme values from CSS custom properties. A string such as "primary" resolves --mm-color-primary; pass { token: '--app-brand-color', value: '#12b76a' } when the application needs an explicit value.

<ColorPicker
  tokenOptions={[
    'primary',
    'danger',
    { token: '--app-brand-color', label: 'Brand' },
  ]}
/>

EyeDropper and contrast

showEyeDropper adds a native screen-color picker where the browser supports the EyeDropper API. The control remains disabled when the API is unavailable. showContrast displays the WCAG contrast ratio against contrastAgainst.

<ColorPicker
  showEyeDropper
  showContrast
  contrastAgainst="#ffffff"
  onChange={(value) => setForeground(value)}
/>

The ratio is informational; the component does not reject colors based on a contrast threshold. The application can use the emitted value to enforce its own AA/AAA policy.

Layout, sizing, and popover behavior

size supports sm, default, and lg. inline keeps the panel open. placement chooses the popover side. portal renders it in document.body, which helps when the picker is inside an overflow-hidden container. popoverWidth accepts pixels or any CSS length.

<ColorPicker size="sm" defaultValue="#2e90fa" />
<ColorPicker size="default" defaultValue="#12b76a" />
<ColorPicker size="lg" defaultValue="#7f56d9" />
<ColorPicker inline label="Inline editor" defaultValue="#f79009" />
<ColorPicker placement="right" portal popoverWidth={320} />

closeOnEscape restores the value that was active when the popover opened and calls onCancel. closeOnOutsideClick controls dismissal when clicking outside. Both are enabled by default. disabled prevents all interaction; readOnly shows the value without opening the editor.

Accessibility and keyboard input

The trigger exposes aria-haspopup="dialog" and aria-expanded. The saturation/brightness area is a keyboard slider: focus it and use Arrow keys; hold Shift for larger steps. Hue, opacity, and text input use native labeled controls. Escape cancels the current session when enabled. Provide aria-label when the visible label is not sufficient context.

API reference

PropTypeDefaultDescription
valuestring—Controlled current color.
defaultValuestring#003231Initial color.
onChange(value: string) => void—Fires for every valid color change.
onCommit(value: string) => void—Fires when a valid value is committed or selected.
onCancel() => void—Fires when Escape cancels the open edit session.
onInvalid(value: string) => void—Fires when text input cannot be parsed.
invalidMessageReactNodeEnter a valid color value.Validation message.
onOpenChange(open: boolean) => void—Fires when the popover opens or closes.
labelReactNode—Visible label.
aria-labelstringColor pickerAccessible name.
formathex | hex8 | rgb | rgba | hsl | hsla | hsb | hsba | hsv | hsvahexOutput and preferred input format.
alphaFormatdecimal | percentagedecimalAlpha representation for alpha-aware formats.
sizesm | default | lgdefaultTrigger size.
inlinebooleanfalseKeeps the panel visible.
showAlphabooleantrueShows opacity control.
showInputbooleantrueShows text input.
showSwatchesbooleantrueShows palette and presets.
swatchesColorPickerPreset[]built-in palettePalette values or labeled entries.
presetsColorPickerPreset[][]Entries shown before the regular palette.
recentColorsstring[][]Initial recent values.
showRecentbooleanfalseShows recent colors.
onSwatchAdd(value: string) => void—Receives the current value from Add current color.
onSwatchRemove(value: string) => void—Receives a recent value on double-click.
swatchShapecircle | squarecircleSwatch shape.
swatchSizenumber | string22Swatch width and height.
showSwatchLabelsbooleanfalseShows the palette heading and titles.
allowCustomSwatchbooleanfalseShows the Add current color action.
allowTransparentbooleanfalseAllows transparent.
showEyeDropperbooleanfalseShows the browser EyeDropper action.
showContrastbooleanfalseShows the calculated contrast ratio.
contrastAgainststring#ffffffComparison color for contrast.
tokenOptionsColorPickerTokenOption[][]CSS-token names or explicit token values.
placementtop | bottom | left | rightbottomPopover placement.
closeOnEscapebooleantrueEscape closes and cancels.
closeOnOutsideClickbooleantrueOutside click closes the popover.
portalbooleanfalseRenders the popover in document.body.
popoverWidthnumber | string248Popover width.
disabledbooleanfalseDisables interaction.
readOnlybooleanfalsePrevents editing and opening.
classNamestring—Additional root class.
styleCSSProperties—Additional root styles.

ColorPickerPreset is string | { value: string; label?: ReactNode }. ColorPickerTokenOption is string | { token: string; value?: string; label?: ReactNode }.