Package Exports
- tailwind-hue-theme
- tailwind-hue-theme/widget
Readme
tailwind-hue-theme
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.
Features
- 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.
Installation
npm install tailwind-hue-themeTailwind v4 plugin
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; }JS config API (Tailwind v4 / v3)
// tailwind.config.js
import { createHuePlugin } from 'tailwind-hue-theme'
export default {
plugins: [
createHuePlugin({ defaultHue: 155, secondaryOffset: 50 }),
],
}createHuePlugin(options?)
| Option | Type | Default | Description |
|---|---|---|---|
defaultHue |
number |
250 |
Starting hue (0–360). Written to --brand-h. |
secondaryOffset |
number |
40 |
Degrees added to --brand-h for the cyan scale. |
buildTokens(options?)
Returns the raw Record<string, string> of CSS custom properties so you can
inspect or test the generated values programmatically.
HuePicker widget
import { HuePicker } from 'tailwind-hue-theme/widget'
const picker = new HuePicker()
// → Floating color wheel appears in the bottom-right corner.Options
| Option | Type | Default | Description |
|---|---|---|---|
defaultHue |
number |
250 |
Initial hue (0–360) if no persisted value exists. |
cssVariable |
string |
'--brand-h' |
CSS custom property updated on <html>. |
storageKey |
string |
'tailwind-hue-theme' |
localStorage key for persistence. |
container |
HTMLElement |
document.body |
Element the widget is appended to. |
onChange |
(hue: number) => void |
— | Called every time the hue changes. |
presets |
HuePreset[] |
6 built-in | Preset swatches. Pass [] to disable. |
Methods
| Method | Description |
|---|---|
getHue(): number |
Returns 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. |
Preset format
interface HuePreset {
label: string // Shown in aria-label and title
hue: number // 0–360
}Built-in presets
| Name | Hue |
|---|---|
| Indigo | 250 |
| Teal | 195 |
| Purple | 295 |
| Rose | 10 |
| Amber | 75 |
| Emerald | 155 |
Custom presets
import { HuePicker } from 'tailwind-hue-theme/widget'
new HuePicker({
presets: [
{ label: 'Sky', hue: 220 },
{ label: 'Pink', hue: 330 },
],
})Programmatic use (no floating UI)
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))
})Color scales
| Scale | Chroma range | Hue expression |
|---|---|---|
slate |
0.004–0.036 | var(--brand-h) |
indigo |
0.03–0.18 | var(--brand-h) |
cyan |
0.03–0.18 | calc(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.
TypeScript
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'License
MIT — see LICENSE.
Created by Peter Benoit