PixelColorInput

Color picker field with a hex text input, native color swatch, and a keyboard-navigable preset grid inside a popover.

  • Outputs hex, rgb(), or hsl() depending on the format prop
  • Popover with native color input, hex draft field, and preset swatch grid
  • Roving tabindex with 2-D arrow key navigation across presets
  • Surface-aware styling for pixel and modern variants
  • Controlled or uncontrolled via value / defaultValue
Status
stable
Category
forms
Since
v1.9.0

API

import { PixelColorInput } from '@pxlkit/ui-kit';
PropTypeDefaultDescription
valuestring—The colour; leave unset for an uncontrolled input.
defaultValuestring—Initial colour while uncontrolled.
onChange(next: string) => void—Called with the colour picked or typed, in format.
format'hex' | 'rgb' | 'hsl''hex'How a picked colour is written: #rrggbb, rgb(r, g, b) or hsl(h, s%, l%).
presetsstring[]—The preset colours; sixteen greys and hues by default.
surface'pixel' | 'linear'—Surface override; defaults to the nearest provider.
size'sm' | 'md' | 'lg''md'Trigger height.
labelstring—Label rendered above the trigger, which it also names.
hintstring—Helper text below the field; hidden while error is set.
errorstring—Error message below the field; marks the trigger invalid.
namestring—Form field name — a hidden input submits the colour.
idstring—id of the trigger; generated when left out.

ref points to <button>.

Accessibility

WCAG target: 2.1 AA

  • popover-dialog
  • roving-tabindex
  • labelled-field

Trigger exposes aria-label; swatches are role=button with the color value as aria-label and aria-pressed reflecting selection.

Keyboard

KeyActionWhen
Enter / SpaceOpen the popover or select the focused swatch—
ArrowRight / ArrowLeftMove focus horizontally across swatches—
ArrowDown / ArrowUpMove focus vertically across the 8-column grid—
Home / EndJump to the first or last swatch—
EscapeClose the popover—

Usage

import { useState } from 'react';
import { PixelColorInput } from '@pxlkit/ui-kit';

export function Default() {
  const [value, setValue] = useState<string>('#06b6d4');
  return (
    <PixelColorInput
      label="Brand color"
      value={value}
      onChange={setValue}
    />
  );
}

Examples

Default

import { useState } from 'react';
import { PixelColorInput } from '@pxlkit/ui-kit';

export function Default() {
  const [value, setValue] = useState<string>('#06b6d4');
  return (
    <PixelColorInput
      label="Brand color"
      value={value}
      onChange={setValue}
    />
  );
}

RGB format

import { useState } from 'react';
import { PixelColorInput } from '@pxlkit/ui-kit';

export function RgbFormat() {
  const [value, setValue] = useState<string>('rgb(34, 197, 94)');
  return (
    <PixelColorInput
      label="Accent color"
      format="rgb"
      value={value}
      onChange={setValue}
      hint="Stored as rgb()"
    />
  );
}

Custom presets

import { useState } from 'react';
import { PixelColorInput } from '@pxlkit/ui-kit';

export function CustomPresets() {
  const [value, setValue] = useState<string>('#ef4444');
  return (
    <PixelColorInput
      label="Theme tone"
      presets={['#ef4444', '#f97316', '#eab308', '#22c55e', '#06b6d4', '#a855f7']}
      value={value}
      onChange={setValue}
    />
  );
}

With error

import { PixelColorInput } from '@pxlkit/ui-kit';

export function WithError() {
  return (
    <PixelColorInput
      label="Background"
      defaultValue="not-a-color"
      error="Invalid color value"
    />
  );
}

Related