Skip to content

Color picker

ColorPicker is a compact one-line color field: a color chip plus a trailing ▐↓▌ dropdown button that opens a ColorSwatch (and an optional hex Input) in a popup anchored to the field. The chip shows the current value as a colored block plus a caption. Picking a swatch cell (releasing over it or pressing Enter) commits the color and closes; with allowCustom on, a hex field accepts any #rrggbb truecolor. The swatch and hex field share the picker's value and stay in sync without churning a named color (e.g. 'red') into its hex form.

Usage

ts
import { ColorPicker, signal } from '@jsvision/ui';
import type { Color } from '@jsvision/core';

const value = signal<Color>('blue');
const picker = new ColorPicker({
  value,
  allowCustom: true, // include a #rrggbb hex field in the popup
  onChange: (c) => console.log('picked', c),
});
picker.setLayout({ position: 'absolute', rect: { x: 0, y: 0, width: 16, height: 1 } });
// Down / Alt+Down / click the ▐↓▌ button opens the swatch; Tab reaches the hex field.

Live example

Open a palette, preview live movement, commit deliberately, and load a custom truecolor value.

Props

new ColorPicker(options).

The public surface is ColorPicker, ColorPickerOptions, its hosted ColorSwatch, and the custom hex Input.

PropTypeDefaultDescription
valueSignal<Color>Two-way selected color (shared with the swatch + hex field).
colorsreadonly Color[]ANSI16_ORDERPalette forwarded to the ColorSwatch.
columnsnumber4Columns forwarded to the ColorSwatch.
allowCustombooleantrueInclude a hex Input for arbitrary #rrggbb truecolor.
labelstringFixed fallback caption used when nameFor is absent.
nameFor(c: Color) => stringName accessor for the chip caption.
onInput(c: Color) => voidFired on every live change in the popup (arrow / click / drag).
onChange(c: Color) => voidFired on the commit gesture (Enter / Space / mouse-up), which also closes.
InputResult
Down / Alt+DownOpen the dropdown swatch.
Click the ▐↓▌ buttonOpen the dropdown swatch.
Pick a swatch cellCommit the color and close (Enter / Space / mouse-up).
Tab (in the popup)Move to the hex field (when allowCustom).
Type #rrggbbSet a custom truecolor; an incomplete/invalid value is ignored.

With no overlay host available (headless), opening is a no-op.

Live preview and commit

Palette movement updates value and calls onInput immediately, which is ideal for reversible preview. Enter, Space, or mouse release calls onChange and closes the popup, creating a clear commit boundary. The custom field follows the same shared value but ignores incomplete or invalid hex text; named colors remain named when their RGB already matches.

Sizing & layout

One row: the color chip plus a trailing 3-cell dropdown button. Give it enough width for the caption and the button.

Best practices

  • Turn on allowCustom for truecolor. The DOS-16 swatch covers the classic palette; the hex field opens the full 24-bit space for anything else.
  • Named values survive. Selecting 'red' stays 'red' — it isn't rewritten to #ff0000 — so themed, named colors round-trip cleanly.
  • Split live vs. committed. onInput/onChange forward to the hosted swatch: preview on onInput, persist on onChange (which also closes the popup).

Theming

The chip uses inputNormal and inputSelected; the popup follows the dialog surface, the swatch marker uses colorMarker, and the ▐↓▌ button uses historyButtonSides and historyButtonArrow.

  • Color swatch — the grid opened by the dropdown.
  • Input — the hex field used for custom truecolor.
  • API reference — the generated ColorPicker signature.