Skip to main content

Theme Switching

Switch between loaded themes with useTheme, or generate new token CSS with getThemeCSS when values change in your app.

Switch loaded themes

Import the themes before selecting them. This example switches between the bundled Vortex and Awen themes:

src/main.tsx
import "@vortexlabs/vortex-themes/themes/vortex/globals.css";
import "@vortexlabs/vortex-themes/themes/awen/globals.css";

Render this button inside <VortexProvider defaultTheme="vortex">:

src/ThemeSwitcher.tsx
"use client";

import { Button, useTheme } from "@vortexlabs/vortex";

export const ThemeSwitcher = () => {
  const { theme, setTheme } = useTheme();
  const isAwen = theme === "awen";

  return (
    <Button onClick={() => setTheme(isAwen ? "vortex" : "awen")}>
      {isAwen ? "Use Vortex" : "Use Awen"}
    </Button>
  );
};

setTheme changes the nearest provider or ThemeScope; it does not load CSS or change the color mode. Load each theme's fonts too.

To change the root theme from inside a nested ThemeScope, use setRootTheme from useTheme.

Choose who owns the state

Use defaultTheme when Vortex should manage the selection. If your app already stores it, pass theme and update that value from your app instead.

BoundaryVortex manages stateYour app manages state
VortexProviderdefaultTheme + setThemetheme
ThemeScopedefaultName + setThemename

A controlled theme or name takes precedence over the hook's setter. Vortex keeps its selection in memory; your app owns persistence. For server rendering, use the same initial theme in the provider and root HTML attributes, as shown in the Next.js guide.

Preview live token changes

Use getThemeCSS for a theme editor or live preview. It returns CSS for the tokens you pass, without adding default tokens. Keep a complete base theme loaded.

Render this example inside your acme provider, after loading its generated globals.css:

src/ThemePreview.tsx
"use client";

import { useState } from "react";
import { Button, ThemeScope } from "@vortexlabs/vortex";
import { getThemeCSS } from "@vortexlabs/vortex-themes";

export const ThemePreview = () => {
  const [rounded, setRounded] = useState(false);
  const css = getThemeCSS("preview", {
    componentTokens: {
      borderRadius: {
        button: { borderRadius: rounded ? "full" : "sm" },
      },
    },
  });

  return (
    <>
      <style>{css}</style>
      <ThemeScope name={["acme", "preview"]}>
        <Button onClick={() => setRounded((value) => !value)}>
          {rounded ? "Use small corners" : "Use round corners"}
        </Button>
      </ThemeScope>
    </>
  );
};

Place the generated styles after the base CSS. Give each independent preview its own theme name; two previews named preview overwrite each other's styles.

Tokens use the same format as Create a Theme. getThemeCSS returns token variables only; generate typography, breakpoints, and Tailwind mappings with the CLI.

Tailwind utilities read the updated variables, so no new classes are needed.