@styleglide/theme-editor
You can load the StyleGlide theme editor into any app that uses the shadcn/ui design system with this lightweight, zero-dependency JS package.
Quickstart
Initialize the theme editor via CDN.
<html lang="en">
<head>
<!-- Add to your HTML head -->
<script defer src="https://unpkg.com/@styleglide/theme-editor"></script>
</head>
<body>
<!-- ... -->
</body>
</html>
import Script from "next/script";
export default function RootLayout({ children }) {
return (
<html>
<body>
<Script src="https://unpkg.com/@styleglide/theme-editor" />
{children}
</body>
</html>
);
}
This line of code is all you need to start using the theme editor.
- A button that activates it will appear in the bottom center of your screen
- StyleGlide generates Tailwind CSS palettes and shadcn/ui themes on demand
- Your application updates with a real-time preview
- You can copy the current theme or install it with the shadcn CLI
What the CDN install handles automatically:
- Checks
dark
class on<html>
andtheme
inlocalStorage
for mode toggle integration - Detects CSS
channels
vscolorSpace
format in CSS theme vars
Manual Setup
For more control over how the theme editor is initialized, you can install the package via NPM.
For this example we'll use the Next.js App Router, but the basics remain the same for any React app.
Note: React is not required to run the theme editor. In fact, you can even use it with shadcn/ui ports that use more traditional web stacks such as basecoat.
Install the package
pnpm add @styleglide/theme-editor
npm install @styleglide/theme-editor
yarn add @styleglide/theme-editor
bun add @styleglide/theme-editor
Set up a component to import and initialize the theme editor
"use client";
import { themeEditor } from "@styleglide/theme-editor";
export function ThemeEditor() {
useEffect(() => {
themeEditor();
}, []);
return null;
}
Control initialization with the enabled prop
export function ThemeEditor() {
useEffect(() => {
themeEditor({
enabled: process.env.NODE_ENV === "development",
});
}, []);
return null;
}
Integrate light and dark mode
If your app has system
mode, make sure to pass in the resolved mode of light
or dark
.
import { useTheme } from "next-themes";
export function ThemeEditor() {
const { setTheme, resolvedTheme } = useTheme();
useEffect(() => {
themeEditor({
enabled: process.env.NODE_ENV === "development",
onChangeMode: setTheme,
resolvedMode: resolvedTheme, // "light" | "dark"
});
}, [resolvedTheme, setTheme]);
return null;
}
Set the CSS color format to match your shadcn/ui theme vars
The default format is colorSpace
and works for vars that include the color space function like hsl(0 0% 45.1%)
or oklch(0.56 0.00 0)
. This is typical for Tailwind v4.
Use channels
if your vars look like 0 0% 45.1%
. This is typical for Tailwind v3.
export function ThemeEditor() {
const { setTheme, resolvedTheme } = useTheme();
useEffect(() => {
themeEditor({
enabled: process.env.NODE_ENV === "development",
onChangeMode: setTheme,
resolvedMode: resolvedTheme,
cssColorFormat: "channels", // "channels" | "colorSpace"
});
}, [resolvedTheme, setTheme]);
return null;
}
Add the theme editor component to your root layout
Make sure to place it as a child of your light/dark mode provider.
import { ReactNode } from "react";
import { ThemeEditor } from "@/components/theme-editor";
import { ThemeProvider } from "next-themes";
export default function RootLayout({ children }: { children: ReactNode }) {
return (
<html lang="en" suppressHydrationWarning>
<body>
<ThemeProvider>
<ThemeEditor />
{children}
</ThemeProvider>
</body>
</html>
);
}
Custom Open Button
By default, the theme editor creates a floating StyleGlide button to open the editor. You can use your own custom button instead by adding the data-theme-editor-open
attribute:
<button data-theme-editor-open>Open Theme Editor</button>
API Reference
themeEditor
The main function to initialize the theme editor.
themeEditor(options: ThemeEditorOptions): void
type ThemeEditorOptions
An object containing the configuration for the theme editor.
Property | Type | Default |
---|---|---|
resolvedMode | 'light' | 'dark' | 'light' |
onChangeMode | (mode: 'light' | 'dark') => void | - |
enabled | boolean | true |
cssColorFormat | 'channels' | 'colorSpace' | 'colorSpace' |