@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.

index.html
<html lang="en">
  <head>
    <!-- Add to your HTML head -->
    <script defer src="https://unpkg.com/@styleglide/theme-editor"></script>
  </head>
  <body>
    <!-- ... -->
  </body>
</html>
layout.tsx
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> and theme in localStorage for mode toggle integration
  • Detects CSS channels vs colorSpace 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

components/theme-editor.tsx
"use client";

import { themeEditor } from "@styleglide/theme-editor";

export function ThemeEditor() {
  useEffect(() => {
    themeEditor();
  }, []);

  return null;
}

Control initialization with the enabled prop

components/theme-editor.tsx
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.

components/theme-editor.tsx
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.

components/theme-editor.tsx
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.

layout.tsx
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.

PropertyTypeDefault
resolvedMode'light' | 'dark''light'
onChangeMode(mode: 'light' | 'dark') => void-
enabledbooleantrue
cssColorFormat'channels' | 'colorSpace''colorSpace'