Skip to content

Instantly share code, notes, and snippets.

@andresgutgon
Last active June 13, 2026 19:15
Show Gist options
  • Select an option

  • Save andresgutgon/32e232d094d43a476b138f668e16ca63 to your computer and use it in GitHub Desktop.

Select an option

Save andresgutgon/32e232d094d43a476b138f668e16ca63 to your computer and use it in GitHub Desktop.
Multi hue setup
import type { CSSProperties, ReactNode } from "react";
const hues = {
summer: "--summer-hue",
green: "--green-hue",
ocean: "--ocean-hue",
sunset: "--sunset-hue",
} as const;
type HueName = keyof typeof hues;
export function App({ hue, children }: { hue: HueName; children: ReactNode }) {
return (
<div data-hue={hue} style={{ "--hue": `var(${hues[hue]})` } as CSSProperties}>
{children}
</div>
);
}
// <App hue="summer" />
@import "tailwindcss";
/* class-based dark mode: toggle `.dark` on <html> (or any subtree) */
@custom-variant dark (&:where(.dark, .dark *));
@layer base {
/* ── palette hues used in the app ─────────────────────────────── */
:root {
--summer-hue: 320;
--green-hue: 150;
--ocean-hue: 230;
--sunset-hue: 25;
--hue: var(--summer-hue); /* default palette */
}
/* Set the active hue on any element/subtree. Because the ramp + tokens
below are re-declared on [data-hue], var(--hue) resolves locally, so a
nested <div data-hue="ocean"> retints just that subtree. */
[data-hue="summer"] { --hue: var(--summer-hue); }
[data-hue="green"] { --hue: var(--green-hue); }
[data-hue="ocean"] { --hue: var(--ocean-hue); }
[data-hue="sunset"] { --hue: var(--sunset-hue); }
/* ── OKLCH ramp + light tokens (root and every hue boundary) ───── */
:root,
[data-hue] {
--swatch-1: oklch(99% 0.05 var(--hue));
--swatch-2: oklch(90% 0.1 var(--hue));
--swatch-3: oklch(80% 0.2 var(--hue));
--swatch-4: oklch(72% 0.25 var(--hue));
--swatch-5: oklch(67% 0.31 var(--hue));
--swatch-6: oklch(50% 0.27 var(--hue));
--swatch-7: oklch(35% 0.25 var(--hue));
--swatch-8: oklch(25% 0.2 var(--hue));
--swatch-9: oklch(13% 0.2 var(--hue));
--swatch-10: oklch(5% 0.1 var(--hue));
--background: var(--swatch-2);
--foreground: var(--swatch-10);
--card: var(--swatch-1);
--card-foreground: var(--swatch-10);
--popover: var(--swatch-1);
--popover-foreground: var(--swatch-10);
--primary: var(--swatch-6);
--primary-foreground: var(--swatch-1);
--secondary: var(--swatch-3);
--secondary-foreground: var(--swatch-10);
--muted: var(--swatch-3);
--muted-foreground: var(--swatch-7);
--accent: var(--swatch-4);
--accent-foreground: var(--swatch-10);
--border: var(--swatch-3);
--input: var(--swatch-3);
--ring: var(--swatch-5);
}
/* ── dark tokens (root scope + any hue boundary within it) ─────── */
.dark,
.dark [data-hue] {
--background: var(--swatch-10);
--foreground: var(--swatch-1);
--card: var(--swatch-9);
--card-foreground: var(--swatch-1);
--popover: var(--swatch-9);
--popover-foreground: var(--swatch-1);
--primary: var(--swatch-5);
--primary-foreground: var(--swatch-10);
--secondary: var(--swatch-8);
--secondary-foreground: var(--swatch-1);
--muted: var(--swatch-8);
--muted-foreground: var(--swatch-3);
--accent: var(--swatch-7);
--accent-foreground: var(--swatch-1);
--border: var(--swatch-8);
--input: var(--swatch-8);
--ring: var(--swatch-5);
}
* {
border-color: var(--border);
}
body {
background-color: var(--background);
color: var(--foreground);
}
}
/* ── expose tokens as Tailwind color utilities ──────────────────────
`inline` keeps them as live var() refs, so utilities resolve at the
element — picking up the nearest --hue and .dark instead of being
frozen at build time. This is what makes bg-background / text-foreground
react to both hue and theme. */
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-card: var(--card);
--color-card-foreground: var(--card-foreground);
--color-popover: var(--popover);
--color-popover-foreground: var(--popover-foreground);
--color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground);
--color-secondary: var(--secondary);
--color-secondary-foreground: var(--secondary-foreground);
--color-muted: var(--muted);
--color-muted-foreground: var(--muted-foreground);
--color-accent: var(--accent);
--color-accent-foreground: var(--accent-foreground);
--color-border: var(--border);
--color-input: var(--input);
--color-ring: var(--ring);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment