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
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
npm install @lemonadejs/color
import Color from '@lemonadejs/color';
import '@lemonadejs/color/style.css';
Three deployment forms, one component:
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) |
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 openedonclose— popup closed (origin)onchange— the picked color changed (user-initiated)
API
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:
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.