Skip to content
Devix Open Source

Guide

React, Vue, Svelte and a plain page

Every wrapper is a thin layer over the same DOM core, so all of them behave identically — the same keyboard, the same ARIA, the same colour maths, the same bugs fixed once.

React

import { ColorField } from '@devix-labs/color-picker/react';
import '@devix-labs/color-picker/styles.css';

function Brand() {
  const [color, setColor] = useState('#3a86ff');

  return (
    <ColorField
      value={color}
      format="oklch"
      contrastAgainst="#ffffff"
      swatches={['#3a86ff', '#8338ec', '#ffbe0b']}
      onChange={setColor}
      onCommit={save}
    />
  );
}

Controlled or uncontrolled: pass value and it follows, or leave it out and read the colour from onCommit. It renders a plain <input>, so it is safe to server-render — the widget is built when the effect runs, in the browser.

Vue

<script setup>
import { onMounted, onBeforeUnmount, ref } from 'vue';
import { colorField } from '@devix-labs/color-picker/vue';
import '@devix-labs/color-picker/styles.css';

const host = ref(null);
let picker;

onMounted(() => {
  picker = colorField(host.value, { format: 'oklch', onCommit: (value) => emit('update:modelValue', value) });
});
onBeforeUnmount(() => picker?.destroy());
</script>

<template>
  <input ref="host" :value="modelValue">
</template>

Svelte

<script>
  import { color } from '@devix-labs/color-picker/svelte';
  import '@devix-labs/color-picker/styles.css';

  let value = '#3a86ff';
</script>

<input use:color={{ value, format: 'oklch', onCommit: (v) => (value = v) }}>

A web component

<script type="module" src="https://devix.pk/cdn/oss/color-picker@1.0.0/element.js"></script>

<dx-color name="brand" value="#3a86ff" format="oklch" contrast-against="#ffffff"
          swatches="#3a86ff #8338ec #ffbe0b"></dx-color>

Attributes: name, value, format, contrast-against, swatches (space or comma separated), no-alpha. It exposes .value and .picker, and fires change with event.detail.value.

A plain page, from the CDN

<link rel="stylesheet" href="https://devix.pk/cdn/oss/color-picker@1.0.0/color-picker.min.css">
<script src="https://devix.pk/cdn/oss/color-picker@1.0.0/color-picker.min.js"></script>
<script>
  DevixColorPicker.createColorPicker(document.querySelector('#brand'));
</script>

The global carries the colour maths too: DevixColorPicker.contrast, .parse, .format, .rgbToOklch and the rest.

Blade, Livewire and Alpine

Because the picker drives a real <input> and fires input and change on it, nothing needs wiring:

<input id="brand" name="brand" value="{{ old('brand', $settings->brand) }}" wire:model.blur="brand">
<script type="module">
  import { createColorPicker } from '/cdn/oss/color-picker@1.0.0/index.js';
  createColorPicker(document.querySelector('#brand'), { format: 'oklch' });
</script>

wire:model.blur, x-model, FormData, $request->input('brand') and a plain POST all see the value, because there is only ever one field.

Server rendering

Nothing touches window at import time, so importing the package on a server is safe in Next.js, Nuxt, SvelteKit and Astro. The widget is built when the component mounts.

Updated 15 Sep 2026