Documentation Index
Fetch the complete documentation index at: https://subframe-59800133-gtmbot-restructure-dark-mode-docs-v2.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
When you enable dark mode in your theme, the CLI generates your color tokens as CSS variables instead of hardcoded values. Light mode values load by default, and dark mode values activate when a dark class is present on the page. This guide covers how to toggle between them.
How the generated code works
The CLI syncs two files:
tailwind.config.js — references CSS variables instead of hardcoded values, with darkMode: 'selector' enabled
theme.css — defines :root variables for light mode and .dark overrides for dark mode
module.exports = {
darkMode: 'selector',
theme: {
extend: {
colors: {
"brand-primary": "rgb(var(--color-brand-primary) / <alpha-value>)",
// ... all color tokens as CSS variable references
},
},
},
}
:root {
--color-brand-primary: 26 26 26;
--color-default-background: 252 252 252;
/* ... light mode values */
}
.dark {
--color-brand-primary: 212 212 212;
--color-default-background: 10 10 10;
/* ... dark mode overrides */
}
Import theme.css in your global stylesheet or entry point:@import "./subframe/theme.css";
The generated theme.css includes a @custom-variant for dark mode and a .dark block with overrides:@custom-variant dark (&:where(.dark, .dark *));
@theme {
--color-brand-primary: rgb(26 26 26);
--color-default-background: rgb(252 252 252);
/* ... light mode values */
}
.dark {
--color-brand-primary: rgb(212 212 212);
--color-default-background: rgb(10 10 10);
/* ... dark mode overrides */
}
Sync your theme
Run the CLI to sync your theme (including dark mode) to your codebase:
npx @subframe/cli@latest sync --all
Add a toggle
To switch between light and dark mode, your app needs to toggle the dark class on the <html> element. Here’s how to set that up:
Next.js (next-themes)
Vite / React
Wrap your app in the ThemeProvider
import { ThemeProvider } from "next-themes"
export default function RootLayout({ children }) {
return (
<html suppressHydrationWarning>
<body>
<ThemeProvider attribute="class" defaultTheme="system">
{children}
</ThemeProvider>
</body>
</html>
)
}
Add a toggle button
import { useTheme } from "next-themes"
export function ThemeToggle() {
const { theme, setTheme } = useTheme()
return (
<button onClick={() => setTheme(theme === "dark" ? "light" : "dark")}>
{theme === "dark" ? "Light mode" : "Dark mode"}
</button>
)
}
Create a ThemeProvider
import { createContext, useContext, useEffect, useState } from "react"
const ThemeContext = createContext({ theme: "light", toggleTheme: () => {} })
export function ThemeProvider({ children }) {
const [theme, setTheme] = useState(() => {
if (typeof window !== "undefined") {
return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"
}
return "light"
})
useEffect(() => {
document.documentElement.classList.remove("light", "dark")
document.documentElement.classList.add(theme)
}, [theme])
const toggleTheme = () => setTheme(theme === "light" ? "dark" : "light")
return <ThemeContext.Provider value=undefined>{children}</ThemeContext.Provider>
}
export const useTheme = () => useContext(ThemeContext)
Wrap your app
import { ThemeProvider } from "./ThemeProvider"
ReactDOM.createRoot(document.getElementById("root")!).render(
<ThemeProvider>
<App />
</ThemeProvider>
)
Add a toggle button
import { useTheme } from "./ThemeProvider"
export function ThemeToggle() {
const { theme, toggleTheme } = useTheme()
return (
<button onClick={toggleTheme}>
{theme === "dark" ? "Light mode" : "Dark mode"}
</button>
)
}