apx-dsv0.1Local renderer · live
K
Foundations4
  • Getting started
  • Theming
  • Templates
  • Icons
  • Avatar
  • Badge
  • DataGrid
  • Scheduler
  • Stat
  • Table
  • Timeline
  • TreeView
  • Accordion
  • Alert
  • EmptyState
  • Progress
  • Skeleton
  • Spinner
  • SplashScreen
  • Toast
  • ColorPicker
  • FileUpload
  • Form
  • Rating
  • TagsInput
  • Combobox
  • Field
  • Select
  • Toggle
  • Button
  • Calendar
  • Checkbox
  • DatePicker
  • Input
  • NumberInput
  • Radio
  • Slider
  • Switch
  • Textarea
  • AppShell
  • Div
  • Divider
  • Sidebar
  • Stack
  • Typography
  • Image
  • Breadcrumbs
  • Carousel
  • NavigationMenu
  • Pagination
  • Stepper
  • Tabs
  • Toolbar
  • CommandPalette
  • Confirm
  • Drawer
  • HoverCard
  • Menu
  • Modal
  • Popover
  • Tooltip
  • Icon
  • Card
  • PricingCard
60 componentsapx-ds/renderer
ColorPicker
Variant↳ other

Form

ColorPicker

Visual color form control: saturation/lightness square + hue slider + alpha + presets + tabbed hex/rgb/hsl text input. Includes <ColorSwatch /> for read-only chips and <ColorInput /> for text-only entry. Pure color math with no external library.

ColorPicker

The canonical visual color form control. Three exports cover three jobs:

  • <ColorPicker /> — the full visual picker. Saturation/lightness square + hue slider + alpha + presets + tabbed hex/rgb/hsl text input, all packed inside a Popover. The default.
  • <ColorSwatch /> — read-only display chip. Use for brand swatches, label colors, theme previews.
  • <ColorInput /> — text-only entry. Use when you want hex / rgb / hsl entry without the visual picker (e.g. a Theme Studio token row, a CLI-style color field).

All three share the same pure color math in _shared/color.ts (~120 LoC, no external library).

Overview — brand color picker with default trigger

Loading preview…
Overview.tsx

Why this exists

Visual color pickers are full of subtle mistakes when hand-rolled:

  • ❌ Two thumb-and-track sliders for hue and alpha get the W3C Slider keyboard pattern wrong.
  • ❌ Saturation/value squares miss the role="slider" 2D pattern entirely.
  • ❌ Hex inputs accept invalid input silently.
  • ❌ RGB / HSL inputs don't clamp or round-trip cleanly.
  • ❌ Alpha rendering forgets the checker transparency background.
  • ❌ Eyedropper buttons render unconditionally and fail in non-Chrome browsers.
  • ❌ No WCAG contrast feedback when the picker is being used to set text or button colors.

<ColorPicker /> fixes every one of those.

Anatomy

tsx
┌──────────────────────────────────────────────────┐
│  Brand color *                  ← label          │
│  Used for primary buttons       ← description    │
│  [ ████ ]   #6c5ce7             ← trigger        │
│  WCAG AA recommended            ← helper/error   │
└──────────────────────────────────────────────────┘

    on open ──►  ┌──────────────────────────┐
                  │  ┌────────────────────┐  │  ← saturation square
                  │  │                    │  │
                  │  │        ●           │  │
                  │  └────────────────────┘  │
                  │  ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ●     │  ← hue slider
                  │  ░░░░░░░░░░░░░░░  ●     │  ← alpha slider
                  │  HEX  RGB  HSL          │  ← format tabs
                  │  #6c5ce7                │  ← hex / rgb / hsl row
                  │  ⬛⬛⬛⬛⬛⬛⬛⬛           │  ← presets grid
                  │  4.6:1 ✓ AA      [👁]   │  ← contrast chip + eyedropper
                  └──────────────────────────┘
┌──────────────────────────────────────────────────┐
│  Brand color *                  ← label          │
│  Used for primary buttons       ← description    │
│  [ ████ ]   #6c5ce7             ← trigger        │
│  WCAG AA recommended            ← helper/error   │
└──────────────────────────────────────────────────┘

    on open ──►  ┌──────────────────────────┐
                  │  ┌────────────────────┐  │  ← saturation square
                  │  │                    │  │
                  │  │        ●           │  │
                  │  └────────────────────┘  │
                  │  ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ●     │  ← hue slider
                  │  ░░░░░░░░░░░░░░░  ●     │  ← alpha slider
                  │  HEX  RGB  HSL          │  ← format tabs
                  │  #6c5ce7                │  ← hex / rgb / hsl row
                  │  ⬛⬛⬛⬛⬛⬛⬛⬛           │  ← presets grid
                  │  4.6:1 ✓ AA      [👁]   │  ← contrast chip + eyedropper
                  └──────────────────────────┘

Examples

Basic — controlled value, default trigger

Loading preview…
Basic.tsx

With alpha — rgba / hsla / hex8 output

Loading preview…
WithAlpha.tsx

Format='hex' — forces hex output

Loading preview…
HexFormat.tsx

Format='rgb' — forces rgb output

Loading preview…
RgbFormat.tsx

Format='hsl' — forces hsl output

Loading preview…
HslFormat.tsx

With presets — palette beside the picker

Loading preview…
WithPresets.tsx

Presets-only — chip grid, no freeform

Loading preview…
PresetsOnly.tsx

Eyedropper — gated on browser API availability

Loading preview…
Eyedropper.tsx

Contrast check — live WCAG ratio chip

Loading preview…
ContrastCheck.tsx

Trigger variants — swatch

Loading preview…
TriggerSwatch.tsx

Trigger variants — button

Loading preview…
TriggerButton.tsx

Trigger variants — input

Loading preview…
TriggerInput.tsx

Sizes — sm / md / lg

Loading preview…
Sizes.tsx

In a form — name + required + helperText

Loading preview…
AsFormField.tsx

ColorSwatch — read-only chip in three sizes

Loading preview…
ColorSwatchSizes.tsx

ColorSwatch — with inline labels

Loading preview…
ColorSwatchGroup.tsx

ColorInput — text-only variant

Loading preview…
ColorInputOnly.tsx

Keyboard

SurfaceKeys
TriggerSpace / Enter opens the picker.
Saturation squareArrow* ±1%; Shift+Arrow* ±10%; Home/End for saturation extremes.
Hue sliderArrow ±1°; Shift+Arrow ±15°; PageUp/PageDown ±15°; Home/End.
Alpha sliderSame as hue, in 0..1 with 10% page step.
Hex / RGB / HSL inputEnter commits, Esc reverts.
Preset swatch gridArrow keys move focus, Enter / Space selects.
EyedropperEnter activates browser eyedropper.

A11y

  • Saturation square is a role="slider" with aria-valuetext describing both axes ("S 75%, L 60%").
  • Hue + alpha sliders are full role="slider" controls with the W3C keyboard pattern.
  • Hex / RGB / HSL inputs are plain text inputs with visible per-channel labels.
  • Preset swatches form a role="listbox" with role="option" children.
  • Eyedropper button is hidden entirely when window.EyeDropper is unavailable.
  • Contrast chip announces its WCAG level via aria-label, not color alone.

RTL

The hue and alpha gradients stay visually canonical (red on the left, transparent on the left) because color pickers are visual instruments — the hue wheel doesn't change direction with text reading direction. The underlying role="slider" value semantics still respect RTL through arrow-key flipping.

i18n

Wrap the app in <I18nProvider locale="he" messages={{ ColorPicker: heColorPickerTranslations }}> to translate every visible string. Bundles ship for en, he, ar.

tsx
import { I18nProvider } from '@apx-ds/engine';
import { heColorPickerTranslations } from 'apx-ds';
<I18nProvider locale="he" messages={{ ColorPicker: heColorPickerTranslations }}>
  <ColorPicker defaultValue="#6c5ce7" />
</I18nProvider>;
import { I18nProvider } from '@apx-ds/engine';
import { heColorPickerTranslations } from 'apx-ds';
<I18nProvider locale="he" messages={{ ColorPicker: heColorPickerTranslations }}>
  <ColorPicker defaultValue="#6c5ce7" />
</I18nProvider>;

Props

PropTypeDefaultDescription
ariaLabelstring—Override accessible name when no visible label is provided.
classNamestring—Override className on the trigger.
closeOnSelectboolean—When `presetsOnly`, close the popover the moment a preset is clicked.
contrastAgainststring'#FFFFFF'Background color the contrast chip checks against.
defaultValuestring—Uncontrolled initial color.
descriptionReactNode—Hint text between the label and the trigger.
disabledboolean—Block all interaction.
enableAlphaboolean—When true, the alpha slider appears + alpha is preserved in the emitted string.
enableContrastCheckboolean—Show a contrast chip comparing the current color against `contrastAgainst`.
enableEyedropperboolean—Show the browser EyeDropper API button (gated on `window.EyeDropper`).
errorReactNode—Bottom error text. Announced via `aria-describedby`; sets `data-invalid` on the trigger.
formatenum—Output format. `'auto'` (default) preserves the incoming format. `'hex'` / `'rgb'` / `'hsl'` force the named serialization.
helperTextReactNode—Bottom helper text. Hidden when `error` is set.
hideLabelbooleanfalseVisually hide the label (still sr-only for AT).
idstring—Override id on the trigger.
labelReactNode—Visible label above the trigger (becomes the accessible name when set).
namestring—Hidden-input name for HTML form submission.
onChangeColorPickerChangeHandler—Fires on every committed value change.
presetsreadonly string[]—Optional palette of preset swatches displayed inside the picker.
presetsOnlyboolean—Disable the freeform picker and show only the presets grid.
readOnlyboolean—Render the trigger as static (no popover).
requiredboolean—Sets `required` on the hidden input (native validation carries the semantics).
sizeenum'md'Visual density.
styleCSSProperties—Standard inline style.
sxSx—Theme-aware inline style object.
translationsPartial<ColorPickerTranslations>—Per-instance translations override. Falls back to the I18nProvider, then English defaults.
triggerVariantenum'swatch'Trigger shape.
valuestring—Controlled color (any CSS-valid format). Pair with `onChange`.