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
import { PixelColorInput } from '@pxlkit/ui-kit';
| Prop | Type | Default | Description |
|---|
value | string | — | The colour; leave unset for an uncontrolled input. |
defaultValue | string | — | 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%). |
presets | string[] | — | 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. |
label | string | — | Label rendered above the trigger, which it also names. |
hint | string | — | Helper text below the field; hidden while error is set. |
error | string | — | Error message below the field; marks the trigger invalid. |
name | string | — | Form field name — a hidden input submits the colour. |
id | string | — | id of the trigger; generated when left out. |
ref points to <button>.
WCAG target: 2.1 AA
popover-dialogroving-tabindexlabelled-field
Trigger exposes aria-label; swatches are role=button with the color value as aria-label and aria-pressed reflecting selection.
Keyboard
| Key | Action | When |
|---|
| Enter / Space | Open the popover or select the focused swatch | — |
| ArrowRight / ArrowLeft | Move focus horizontally across swatches | — |
| ArrowDown / ArrowUp | Move focus vertically across the 8-column grid | — |
| Home / End | Jump to the first or last swatch | — |
| Escape | Close the popover | — |
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"
/>
);
}