---
title: "JavaScript Color Picker"
description: "The LemonadeJS Color Picker block for JavaScript: Palette and gradient color picker. Contract-verified, framework-agnostic, zero dependencies, with a live example."
source: https://lemonadejs.com/docs/plugins/color/
---

<link rel="stylesheet" href="/v6/modal.css">
<link rel="stylesheet" href="/v6/color.css">

# JavaScript Color Picker

`@lemonadejs/color` · ✓ 18 contract checks · framework-agnostic · zero dependencies

`<Color />` — color picker on the Modal primitive (v5 architecture).

Faithful port of @lemonadejs/color: a Grid tab (the material palette
matrix, custom palettes supported, the picked cell marked with a
checkmark) and a Spectrum tab (canvas gradient, drag to sample pixels),
Reset/Done bar, popup built ON Modal exactly as v5 built on
@lemonadejs/modal (headerless, absolute, auto-adjust, no focus steal),
optional text input toggle with the full v5 keyboard system
(ArrowUp/Down opens, Enter commits, Escape closes) and focusout close.

v5 → v6 mapping: value → bind; closeOnChange → closeonchange;
input: 'auto' → type="input" (the block renders its own input — adopting
an external element was dropped, incompatible with by-value blocks);
type: 'inline' keeps its meaning (panel without a popup, selection
commits immediately since the Done bar is a popup affordance);
@lemonadejs/tabs → internal lm-color-tabs strip (no Tabs block in v6).
onclose(origin): 'select' | 'button' | 'escape' | 'focusout' | 'api'.

## Example

<!--example-->

```js
import { html } from 'lemonadejs';
import Color from '@lemonadejs/color';

const App = (props, { state }) => {
    const brand = state('#2563eb');
    const accent = state('#f59e0b');

    return html`<div style="display:grid;gap:12px;max-width:320px">
        <${Color} type="input" bind="${brand}" placeholder="Brand color" />
        <${Color} type="input" bind="${accent}" closeonchange placeholder="Accent (closes on pick)"
            palette="${[
                ['#ef4444', '#f97316', '#f59e0b', '#84cc16', '#10b981'],
                ['#06b6d4', '#3b82f6', '#8b5cf6', '#ec4899', '#64748b'],
            ]}" />
        <div style="${() => 'padding:16px;border-radius:8px;color:#fff;background:' + brand.value + ';border-left:8px solid ' + accent.value}">
            Brand <b>${brand}</b> with accent <b>${accent}</b>
        </div>
    </div>`;
};
```

## Installation

```bash
npm install @lemonadejs/color
```

```js
import Color from '@lemonadejs/color';
import '@lemonadejs/color/style.css';
```

Three deployment forms, one component:

```js
html`<${Color} />`                       // by value (no registration)
setComponents({ Color });               // then <Color /> by name anywhere
createWebComponent(Color);              // <lm-color> in plain HTML/any framework
```

## Props

Every declared prop arrives as a **live state** — pass a value for a snapshot or a
state for a two-way live wire. Attribute strings are coerced to the declared type.

| Prop | Type | Default | Description |
|---|---|---|---|
| `bind` | string | — | Two-way bound value. `.set()` fires `onchange`; plain assignment is silent. the picked color (v5: value) |
| `name` | string | `''` | form field name — root reflects el.value (form-associated) |
| `palette` | array | — | string[][] matrix — a flat string[] becomes one row |
| `type` | string | `''` | '' (popup via api) | 'input' | 'inline' |
| `placeholder` | string | `''` | input placeholder (v5) |
| `aria-label` | string | `''` |  |
| `closeonchange` | boolean | `false` | v5: closeOnChange — picking commits + closes immediately |

## Events

All event names are lowercase (the platform convention — LJS-305 warns otherwise).

- `onopen` — popup opened
- `onclose` — popup closed (origin)
- `onchange` — the picked color changed (user-initiated)

## API

```js
import { ref } from 'lemonadejs';
const color = ref();
html`<${Color} ref="${color}" />`;
// color.current.open(...)  ·  color.current.close(...)  ·  color.current.isClosed(...)  ·  color.current.reset(...)  ·  color.current.setValue(...)  ·  color.current.getValue(...)
```

- `open()`
- `close()`
- `isClosed()`
- `reset()`
- `setValue()`
- `getValue()`

## Styling

All classes follow the `lm-color-*` convention; visual variants are `data-*`
attributes on the root. Override freely — there is no styling engine to fight.

## Contract

The machine-readable schema ships with the package:

```js
import contract from '@lemonadejs/color/contract.json';
```

`verify.json` carries the conformance proof produced by `verify(Color)`.

Looking for the v5 plugin? See the [archived v5 documentation](/docs/v5/plugins/).