ThemeStudio
Live editor for the active palette's CSS custom properties. Seeds its values from the currently-rendered theme via getComputedStyle and writes edits straight to document.documentElement, so changes are visible instantly.
Installation
pnpm dlx shadcn@latest add @shadmin/theme-studioUsage
import { ThemeProvider } from "@/components/admin";
import { ThemeStudio } from "@/components/extras/theme-studio";
<ThemeProvider>
<ThemeStudio />
</ThemeProvider>;ThemeStudio takes no theme prop — it reads the live token values off
:root (over a fixed list of shadcn semantic tokens), so it always reflects
whatever palette and mode are currently active. Editing a value writes it to
document.documentElement.style via setProperty, so the surrounding admin UI
updates immediately — no rebuild, no reload. Color-valued tokens (e.g.
oklch(...), #aabbcc, rgb(...)) get a swatch + color-picker; size-valued
tokens get a numeric input plus a unit select. Requires a surrounding
<ThemeProvider> for the light/dark mode toggle to work.
Props
| Prop | Required | Type | Default | Description |
|---|---|---|---|---|
showExport | Optional | boolean | true | Whether to render the Export button. |
showThemeModeToggle | Optional | boolean | true | Whether to render the light/dark mode toggle. |
className | Optional | string | - | CSS class applied to the outer card. |
showExport
Toggles the Export button (default true). Set to false to hide it
entirely — useful when the studio is embedded in a settings panel that has its
own save flow.
<ThemeStudio showExport={false} />showThemeModeToggle
Toggles the built-in light/dark mode toggle in the card header (default
true). The studio edits whichever mode is currently active, so flipping the
mode lets you tune the light and dark variants separately.
<ThemeStudio showThemeModeToggle={false} />className
Custom class applied to the outer Card. Combine with cn to tweak the
default max-h-[60vh] overflow-y-auto.
<ThemeStudio className="max-h-[80vh]" />Export
The Export button copies a CSS snippet to the clipboard via
navigator.clipboard.writeText — a :root { … } block for the edits made in
light mode and a .dark { … } block for those made in dark mode (each block is
emitted only once you've edited that mode). Paste the snippet into your
globals.css to persist the changes.
Edits are not persisted by the component — reload reverts to the stylesheet's values. Persistence is the caller's responsibility (typical pattern: export the CSS and paste it into your theme stylesheet).
Limitations
- Edits the semantic shadcn tokens (
--background,--primary, the chart and sidebar tokens,--radius, …); it does not expose arbitrary custom variables. - No undo/redo — live edits stack on
document.documentElement.style. - No persistence — reload reverts to the stylesheet's values.