Skip to content

Getting Started

A Tailwind CSS v4 plugin that makes your entire color palette shift dynamically based on a single --brand-h CSS variable. Ship light, bring your own color wheel.

Includes an optional HuePicker widget — a floating circular color wheel for live hue selection with drag support, preset swatches, and localStorage persistence.


  • Single variable control — update --brand-h (0–360) and your entire palette shifts: backgrounds, borders, text, and accents.
  • OKLCH color space — perceptually uniform, wide-gamut colors that look great at any hue.
  • Slate + Indigo + Cyan scales all respond to --brand-h. Slate uses low chroma so dark backgrounds stay dark; indigo follows the hue directly; cyan is offset by +40°.
  • Optional HuePicker widget — drag the circular color wheel, click a preset, or call setHue() from code.
  • localStorage persistence — selected hue survives page reloads.
  • Zero runtime dependencies — ships CJS + ESM + .d.ts.

Terminal window
npm install tailwind-hue-theme

Add to your CSS:

@import "tailwindcss";
@plugin "tailwind-hue-theme";

That’s it. The plugin injects --brand-h: 250 (indigo) into :root and remaps --color-slate-*, --color-indigo-*, and --color-cyan-* to OKLCH values that track --brand-h at runtime.

Switch the palette live from JavaScript:

// Drop-in anywhere — no framework required
document.documentElement.style.setProperty('--brand-h', '155') // Emerald
document.documentElement.style.setProperty('--brand-h', '10') // Rose
document.documentElement.style.setProperty('--brand-h', '250') // Indigo (default)

Override the default hue in CSS without JavaScript:

@plugin "tailwind-hue-theme";
:root { --brand-h: 155; }

tailwind.config.js
import { createHuePlugin } from 'tailwind-hue-theme'
export default {
plugins: [
createHuePlugin({ defaultHue: 155, secondaryOffset: 50 }),
],
}
OptionTypeDefaultDescription
defaultHuenumber250Starting hue (0–360). Written to --brand-h.
secondaryOffsetnumber40Degrees added to --brand-h for the cyan scale.

Returns the raw Record<string, string> of CSS custom properties so you can inspect or test the generated values programmatically.


import { HuePicker } from 'tailwind-hue-theme/widget'
const picker = new HuePicker()
// → Floating color wheel appears in the bottom-right corner.
OptionTypeDefaultDescription
defaultHuenumber250Initial hue (0–360) if no persisted value exists.
cssVariablestring'--brand-h'CSS custom property updated on <html>.
storageKeystring'tailwind-hue-theme'localStorage key for persistence.
containerHTMLElementdocument.bodyElement the widget is appended to.
onChange(hue: number) => voidCalled every time the hue changes.
presetsHuePreset[]6 built-inPreset swatches. Pass [] to disable.
MethodDescription
getHue(): numberReturns the current hue (0–360).
setHue(n: number)Programmatically set hue. Normalises values outside 0–360.
destroy()Removes all DOM nodes and the injected <style> tag.
interface HuePreset {
label: string // Shown in aria-label and title
hue: number // 0–360
}
NameHue
Indigo250
Teal195
Purple295
Rose10
Amber75
Emerald155
import { HuePicker } from 'tailwind-hue-theme/widget'
new HuePicker({
presets: [
{ label: 'Sky', hue: 220 },
{ label: 'Pink', hue: 330 },
],
})
import { HuePicker } from 'tailwind-hue-theme/widget'
const picker = new HuePicker({
presets: [], // no swatches
container: document.getElementById('my-container')!,
onChange: (hue) => console.log('hue →', hue),
})
// Drive the palette from your own UI:
document.getElementById('my-slider')!.addEventListener('input', (e) => {
picker.setHue(Number((e.target as HTMLInputElement).value))
})

ScaleChroma rangeHue expression
slate0.004–0.036var(--brand-h)
indigo0.03–0.18var(--brand-h)
cyan0.03–0.18calc(var(--brand-h) + <secondaryOffset>)

The slate scale uses intentionally low chroma so that dark backgrounds (slate-900, slate-950) remain visually dark at any hue — they just gain a subtle tint.


All exports are fully typed. The package ships .d.ts files alongside CJS and ESM bundles.

import { createHuePlugin, buildTokens, type HuePluginOptions } from 'tailwind-hue-theme'
import { HuePicker, DEFAULT_PRESETS, getWidgetCSS, type HuePickerOptions, type HuePreset } from 'tailwind-hue-theme/widget'

MIT — see LICENSE.


Created by Peter Benoit