I spent two days trying to implement changing global variables via a code component. I’m changing the theme from dark to light.
Is something broken in Plasmic?
I spent two days trying to implement changing global variables via a code component. I’m changing the theme from dark to light.
Is something broken in Plasmic?
Hello @se.belobrov
Changing global variants (like a dark/light theme) via a code component in Plasmic does work—but it requires some setup outside of just the component itself.
Plasmic doesn’t currently allow you to toggle global variants entirely within Studio or a standalone code component. Instead, you’ll need to:
PlasmicRootProvider
via the globalVariants
propI’ll walk you through a working setup. But first, I recommend reviewing:
PlasmicRootProvider
API — to understand how it accepts global variants// context/GlobalVariantContext.tsx
import { createContext, useContext, useState } from "react";
interface GlobalVariantContextType {
isDarkMode: boolean;
toggleDarkMode: () => void;
}
const defaultContextValue: GlobalVariantContextType = {
isDarkMode: false,
toggleDarkMode: () => {},
};
const GlobalVariantContext = createContext<GlobalVariantContextType>(defaultContextValue);
export function GlobalVariantProvider({ children }: { children: React.ReactNode }) {
const [isDarkMode, setIsDarkMode] = useState(false);
const toggleDarkMode = () => setIsDarkMode((prev) => !prev);
return (
<GlobalVariantContext.Provider value={{ isDarkMode, toggleDarkMode }}>
{children}
</GlobalVariantContext.Provider>
);
}
export const useGlobalVariant = () => {
const context = useContext(GlobalVariantContext);
return context || defaultContextValue; // fallback inside Studio preview
};
GlobalVariantProvider
// pages/[[...catchall]].tsx
export default function PlasmicLoaderPage(props: {
plasmicData?: ComponentRenderData;
queryCache?: Record<string, unknown>;
}) {
const { plasmicData } = props;
if (!plasmicData || plasmicData.entryCompMetas.length === 0) {
return <Error statusCode={404} />;
}
const pageMeta = plasmicData.entryCompMetas[0];
return (
<GlobalVariantProvider>
<PlasmicWrapper>
<PlasmicComponent component={pageMeta.displayName} />
</PlasmicWrapper>
</GlobalVariantProvider>
);
}
PlasmicRootProvider
// components/PlasmicWrapper.tsx
function PlasmicWrapper({ children }: { children: React.ReactNode }) {
const { isDarkMode } = useGlobalVariant();
return (
<PlasmicRootProvider
loader={PLASMIC}
globalVariants={[{ name: "Theme", value: isDarkMode ? "dark" : "light" }]}
>
{children}
</PlasmicRootProvider>
);
}
Make sure the global variant name ("Theme"
) and values ("dark"
/ "light"
) match exactly with what you defined in Plasmic Studio (they’re case-sensitive).
// components/DarkModeToggle.tsx
import { useGlobalVariant } from "../context/GlobalVariantContext";
export function DarkModeToggle() {
const { isDarkMode, toggleDarkMode } = useGlobalVariant();
return (
<button onClick={toggleDarkMode}>
{isDarkMode ? "Switch to Light Mode" : "Switch to Dark Mode"}
</button>
);
}
// plasmic-init.ts
PLASMIC.registerComponent(DarkModeToggle, {
name: "DarkModeToggle",
props: {},
});
Now you can drag the DarkModeToggle
into any page in Studio.