Color & gradient
The color engine is the deepest part of the kit: a wide-gamut OKLCH picker with CSS Color 4 gamut mapping, shared by the color control and the gradient editor. All three controls on this page are lazy — on the code-split build their modules load the first time a schema asks for them.
Color
Any hex or CSS color-function string is recognized as a shorthand — hex in, but the picker
works in OKLCH and can emit oklch(), hex, rgb() or
hsl() (switch the format inside the picker). P3-only colors survive
instead of clipping. The param is always a CSS-ready string.
#7C5CFF
const blob = target.querySelector(".col-blob path");
const readout = target.querySelector(".col-readout");
const panel = tweaks("Color", {
tint: "#7C5CFF", // or { type: "color", value: "oklch(0.65 0.24 295)" }
});
mount.append(panel.el);
const apply = (p) => {
blob.setAttribute("fill", p.tint);
readout.textContent = p.tint;
};
panel.on(apply);
panel.ready.then(() => apply(panel.params));mount is the panel's slot inside the stage; target is the demo surface it controls. In your own page you'd just document.body.append(panel.el).
Gradient
A Figma-style stop editor: drag stops along the bar, double-click the bar
(or the + button) to add, select a stop to recolor it with the full picker. The value is
{ stops: [{ color, pos }], interpolation } — ready to template into any CSS
gradient. Stops can be authored in oklch() for wide-gamut ramps.
The ramp blends in whichever colour space you pick in the stop editor: switch the mode
to RGB and the blend goes through sRGB (muddier — that's what rgb() blends
look like); OKLCH stays perceptually even. That chosen space rides along as
interpolation, so dropping it into linear-gradient(in …) makes
your CSS match the preview exactly.
const swatch = target.querySelector(".grad-swatch");
const panel = tweaks("Gradient", {
ramp: { type: "gradient", value: { stops: [
{ color: "oklch(0.72 0.19 25)", pos: 0 },
{ color: "oklch(0.86 0.17 95)", pos: 0.5 },
{ color: "oklch(0.72 0.16 280)", pos: 1 },
] } },
angle: [90, 0, 360, 1],
});
mount.append(panel.el);
const apply = (p) => {
const stops = p.ramp.stops.map((s) => `${s.color} ${s.pos * 100}%`).join(", ");
const space = p.ramp.interpolation || "oklch"; // honor the editor's blend space so the swatch matches the picker
swatch.style.background = `linear-gradient(in ${space} ${p.angle}deg, ${stops})`;
};
panel.on(apply);
panel.ready.then(() => apply(panel.params));Image
{ type: "image" } is a drop zone and file picker in one row.
The param is a data URL — drop a file on the control (or click it) and the tile
picks it up as its background.
const tile = target.querySelector(".img-tile");
const panel = tweaks("Image", {
texture: { type: "image" },
});
mount.append(panel.el);
const apply = (p) => {
tile.style.backgroundImage = p.texture ? `url(${p.texture})` : "none";
tile.querySelector("span").style.opacity = p.texture ? 0 : 1;
};
panel.on(apply);
panel.ready.then(() => apply(panel.params));