Huet

shadcn integration

shadcn's components on their own CSS variables. Huet's shadcn adapter paints those variables from the theme you pick, and moves Tailwind's palette onto the theme's hues.

Form states

Error, warning, success and disabled states for inputs, selects, textareas and checkboxes, and matching alerts.

Inputs

As it appears on your card.

Weak: add a number or a symbol.

Available.

Selects, textareas, checkboxes

Free plans pause after 30 days.

Badges

shadcn's badge variants, status badges, and every Tailwind hue as solid, soft and outline badges.

Variants

DefaultSecondaryDestructiveOutlineGhostLink

Status

ActivePendingWarningFailedInfoNew

Every hue: solid, soft, outline, dot

RedRedRedRed
OrangeOrangeOrangeOrange
AmberAmberAmberAmber
YellowYellowYellowYellow
LimeLimeLimeLime
GreenGreenGreenGreen
EmeraldEmeraldEmeraldEmerald
TealTealTealTeal
CyanCyanCyanCyan
SkySkySkySky
BlueBlueBlueBlue
IndigoIndigoIndigoIndigo
VioletVioletVioletViolet
PurplePurplePurplePurple
FuchsiaFuchsiaFuchsiaFuchsia
PinkPinkPinkPink
RoseRoseRoseRose
SlateSlateSlateSlate

Charts

Recharts through shadcn's ChartContainer: the --chart-1 to --chart-5 palette, and series colored with Tailwind's green, amber and red.

Traffic by source
Stacked area, --chart-1 to --chart-3
Browsers
One bar per chart color
Service health
Tailwind green, amber and red series
99.2% uptime3 slow days1 outage
Share
Donut with a label
Design review
Radar, two series
Quota
Radial bars
Devices
Grouped bars

Themes

shadcn's accent classes. Huet keeps each accent's hue and picks a lightness that reads on the theme.

Neutral
no theme class
BadgeSecondary
x
Blue
theme-blue
BadgeSecondary
x
Teal
theme-teal
BadgeSecondary
x
Green
theme-green
BadgeSecondary
x
Yellow
theme-yellow
BadgeSecondary
x
Amber
theme-amber
BadgeSecondary
x
Orange
theme-orange
BadgeSecondary
x
Red
theme-red
BadgeSecondary
x
Rose
theme-rose
BadgeSecondary
x
Purple
theme-purple
BadgeSecondary
x
Violet
theme-violet
BadgeSecondary
x

Code

Shiki with huetShikiTheme and huetShikiTransformer: each block, and each changed row, is a Huet surface.

configurator.tsx+2−2
export function ThemePanel() {
  const [theme, setTheme] = useState(
    themes.Base 
    themes.Sunset 
  )
  const [bg, setBg] = useState(1) 
  const [bg, setBg] = useState(0) 
  return (
    <ThemeConfigurator
      value={theme}
      onChange={setTheme}
      background={bg}
      onBackgroundChange={setBg}
    />
  )
}
theme.ts
import { mountTheme, themes, type Theme } from "huet"
import { mountImages } from "huet/images"
import "huet/styles.css"

const theme: Theme = { neutral: ["#233b91", "#ffffff"] }
const root = document.querySelector<HTMLElement>("#app")!
const colors = mountTheme(root, theme)
const images = mountImages(root, theme) // recolors <img data-huet-recolor>

// Later: dark mode, then another theme, without rerendering
colors.update(theme, { background: 0 })
colors.update(themes.Paperback)
images.update(themes.Paperback)
profile.html
<section class="huet-bg-20 rounded-lg p-6">
  <p class="huet-text-60 mb-4">Manage your profile.</p>
  <input class="huet-bg-10 huet-bg/border-60 border rounded px-3 py-2" />
  <button class="huet-bg-blue-20 hover:huet-bg-blue-30 rounded px-4 py-2">
    Save
  </button>
</section>
paperback.json
{
  "neutral": ["#3d3531", "#e2c1b1"],
  "colorModel": "lab",
  "colors": {
    "red": "#e13639",
    "yellow": "#c89455",
    "green": "#238e5d",
    "blue": "#366caa",
    "purple": "#8e65bf"
  },
  "signalLightness": { "onLight": 0.36, "onDark": 0.55 },
  "images": { "strength": 1, "tint": 0.6 }
}
globals.css
@import "tailwindcss";
@import "huet/tailwind.css";
@import "huet/forms.css";

.toolbar {
  display: flex;
  gap: 0.5rem;
  border-radius: var(--radius);
}
Terminal
npx shadcn@latest init
npx shadcn@latest add card badge chart
pnpm add huet huet-react