diff --git a/packages/docs/docs.json b/packages/docs/docs.json
index 38e5d533..96961bac 100644
--- a/packages/docs/docs.json
+++ b/packages/docs/docs.json
@@ -48,11 +48,11 @@
"pages": [
"guides/mcp-server",
"guides/skills",
- "guides/dark-mode",
"guides/component-docs",
"guides/accessibility",
"guides/testing",
- "guides/publish-to-npm"
+ "guides/publish-to-npm",
+ "guides/dark-mode"
]
},
{
@@ -97,7 +97,8 @@
"learn/theme/customizing-theme",
"learn/theme/importing-tokens",
"learn/theme/exporting-theme",
- "learn/theme/adding-custom-fonts"
+ "learn/theme/adding-custom-fonts",
+ "learn/theme/dark-mode"
]
},
"learn/flows/flows",
diff --git a/packages/docs/guides/dark-mode.mdx b/packages/docs/guides/dark-mode.mdx
index e2451184..348371b8 100644
--- a/packages/docs/guides/dark-mode.mdx
+++ b/packages/docs/guides/dark-mode.mdx
@@ -1,29 +1,14 @@
---
-title: Dark mode
-description: Add dark mode to your project using Subframe's built-in theme support
+title: Dark mode toggle
+description: Add a dark mode toggle to your app using Subframe's generated theme.
---
import CliSyncAllCommand from "/snippets/cli-sync-all-command.mdx"
-Subframe has built-in dark mode support. Enable it in your theme to define light and dark values side by side, then sync to get a fully configured Tailwind setup.
-
-## Enable dark mode
-
-1. Open **Theme** in the top navigation
-2. In the Colors section, click **Add dark mode**
-3. Each token now shows light and dark values — edit the dark values to define your dark palette
-4. Preview your components and pages in both light and dark mode using the light/dark mode toggle in the toolbar
-
-
- Dark mode colors typically invert the scale: light mode's lightest shade becomes dark mode's darkest, and vice versa.
-
-
-To remove dark mode, click **Remove dark mode** in the Colors section. This deletes all dark overrides. You can undo this using version history.
+When you [enable dark mode](/learn/theme/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
-When dark mode is enabled, Subframe generates theme tokens as CSS variables so light and dark values can switch at runtime.
-
@@ -90,22 +75,29 @@ The generated `theme.css` includes a `@custom-variant` for dark mode and a `.dar
-## Sync to code
+## Sync your theme
Run the CLI to sync your theme (including dark mode) to your codebase:
-## Enable dark mode in your app
+## Add a toggle
-To activate dark mode, set the `dark` class on the `` element. Here are a few ways to accomplish that:
+To switch between light and dark mode, your app needs to toggle the `dark` class on the `` element. Here's how to set that up:
-### Next.js with next-themes
+
+
+
+
+
```bash
npm install next-themes
```
+
+
+
```tsx app/layout.tsx
import { ThemeProvider } from "next-themes"
@@ -122,7 +114,31 @@ export default function RootLayout({ children }) {
}
```
-### React with context
+
+
+
+```tsx
+import { useTheme } from "next-themes"
+
+export function ThemeToggle() {
+ const { theme, setTheme } = useTheme()
+
+ return (
+
+ )
+}
+```
+
+
+
+
+
+
+
+
+
```tsx ThemeProvider.tsx
import { createContext, useContext, useEffect, useState } from "react"
@@ -130,54 +146,58 @@ import { createContext, useContext, useEffect, useState } from "react"
const ThemeContext = createContext({ theme: "light", toggleTheme: () => {} })
export function ThemeProvider({ children }) {
- const [theme, setTheme] = useState("light")
+ const [theme, setTheme] = useState(() => {
+ if (typeof window !== "undefined") {
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"
+ }
+ return "light"
+ })
useEffect(() => {
- const root = window.document.documentElement
- root.classList.remove("light", "dark")
- root.classList.add(theme)
+ document.documentElement.classList.remove("light", "dark")
+ document.documentElement.classList.add(theme)
}, [theme])
const toggleTheme = () => setTheme(theme === "light" ? "dark" : "light")
- return {children}
+ return {children}
}
export const useTheme = () => useContext(ThemeContext)
```
-### Theme toggle button
-
-```tsx
-import { useTheme } from "next-themes"
+
+
-export function ThemeToggle() {
- const { theme, setTheme } = useTheme()
+```tsx main.tsx
+import { ThemeProvider } from "./ThemeProvider"
- return
-}
+ReactDOM.createRoot(document.getElementById("root")!).render(
+
+
+
+)
```
-## Best practices
-
-
-
-
-Always test your application in both light and dark modes. Check for:
+
+
-- Sufficient contrast ratios (use browser DevTools)
-- Readability of all text
-- Visibility of borders and dividers
-- Proper styling of interactive states
-
-
-
+```tsx
+import { useTheme } from "./ThemeProvider"
-Use the user's system preference as the default:
+export function ThemeToggle() {
+ const { theme, toggleTheme } = useTheme()
-```tsx
-
+ return (
+
+ )
+}
```
-
-
+
+
+
+
+
diff --git a/packages/docs/learn/theme/customizing-theme.mdx b/packages/docs/learn/theme/customizing-theme.mdx
index 0bed6095..5a2f7497 100644
--- a/packages/docs/learn/theme/customizing-theme.mdx
+++ b/packages/docs/learn/theme/customizing-theme.mdx
@@ -11,7 +11,7 @@ Click **Theme** in the top navigation, or press Cmd + K an
The theme page has a left sidebar for navigating between sections: Colors, Typography, Borders, Corners, and Shadows. Click any section to scroll to it.
-The Colors section header contains the main actions: **Ask AI**, **Import tokens**, **Export**, and a **⋯** menu with **Reset theme** and **Show version history**.
+The Colors section header contains the main actions: **Ask AI**, **Import tokens**, **Export**, and a **â¯** menu with **Reset theme** and **Show version history**.
All changes save automatically and apply immediately across your project.
@@ -25,7 +25,7 @@ Use Ask AI to update your theme from a prompt:
1. Click **Ask AI** in the sidebar
2. Describe your changes: "warmer tones, rounder corners", "make it brutalist", or "retro theme with muted colors and bold typography"
-3. Review the preview — AI updates colors, typography, corners, and shadows
+3. Review the preview â AI updates colors, typography, corners, and shadows
4. Click **Apply** to update your theme
Ask AI can also rename or delete tokens when the changes call for it. All component references update automatically.
@@ -42,9 +42,9 @@ Subframe organizes colors into **color tokens** grouped by **folders**.
Neutral background with default text color
```
-**Color tokens** define individual colors for your design system. They can be used for specific UI purposes like Brand Primary, Default Background, or Neutral Border. Tokens can reference other tokens as aliases (e.g. Brand Primary → Brand 700).
+**Color tokens** define individual colors for your design system. They can be used for specific UI purposes like Brand Primary, Default Background, or Neutral Border. Tokens can reference other tokens as aliases (e.g. Brand Primary â Brand 700).
-**Folders** group related color tokens together. Organize tokens however you want — by brand, by feature, by shade scale, or any grouping that fits your system. A default **Colors** folder holds standalone tokens.
+**Folders** group related color tokens together. Organize tokens however you want â by brand, by feature, by shade scale, or any grouping that fits your system. A default **Colors** folder holds standalone tokens.
To quickly add tokens from an existing design system, see [Importing tokens](/learn/theme/importing-tokens).
@@ -70,6 +70,10 @@ To quickly add tokens from an existing design system, see [Importing tokens](/le
Click any token to open color picker. Set a direct color value or reference another token as an alias.
+### Dark mode
+
+Enable dark mode to add separate light and dark values for each color token. See [Dark mode](/learn/theme/dark-mode) for details.
+
## Typography
Text tokens define typography styles with font family, size, weight, line height, and letter spacing.
@@ -91,10 +95,10 @@ New tokens duplicate the properties from the first token. Typography tokens auto
Click any text token to edit:
-- **Font size** — Pixel value
-- **Line height** — Pixel value
-- **Font weight** — Slider based on font's supported weights
-- **Letter spacing** — Slider from `-0.05em` to `0.05em`
+- **Font size** â Pixel value
+- **Line height** â Pixel value
+- **Font weight** â Slider based on font's supported weights
+- **Letter spacing** â Slider from `-0.05em` to `0.05em`
### Changing font families
@@ -131,9 +135,9 @@ When generating code, border styles turn into explicit values for the border:
Click any border token to edit:
-- **Border style** — Solid or dashed
-- **Border size** — Pixel width
-- **Border color** — Color token reference or direct value
+- **Border style** â Solid or dashed
+- **Border size** â Pixel width
+- **Border color** â Color token reference or direct value
## Corners
@@ -177,11 +181,11 @@ Shadow tokens auto-sort based on perceived shadow effect.
Click any shadow token to edit individual shadow layers. Each layer has:
-- **Inset** — Whether shadow appears inside element
-- **X/Y offset** — Horizontal and vertical offset in pixels
-- **Blur radius** — Blur amount in pixels
-- **Spread radius** — Spread amount in pixels
-- **Color** — Shadow color with opacity
+- **Inset** â Whether shadow appears inside element
+- **X/Y offset** â Horizontal and vertical offset in pixels
+- **Blur radius** â Blur amount in pixels
+- **Spread radius** â Spread amount in pixels
+- **Color** â Shadow color with opacity
Add multiple layers for complex shadow effects.
@@ -193,7 +197,7 @@ Add multiple layers for complex shadow effects.
Apply a theme preset to start fresh:
-1. Click **⋯** in the sidebar and select **Reset theme**
+1. Click **â¯** in the sidebar and select **Reset theme**
2. Browse 10 preset styles
3. Customize brand colors, fonts, and corner radius
4. Toggle between Light and Dark mode
@@ -206,7 +210,7 @@ Each preset configures color palettes (brand, neutral, error, success, warning),
View and restore previous versions of your theme:
-1. Click **⋯** in the sidebar and select **Version history**
+1. Click **â¯** in the sidebar and select **Version history**
2. Browse the timeline and select a version to preview
3. Click **Restore** to revert to that version
@@ -214,4 +218,4 @@ Select **Exit version history** from the same menu to return to editing.
## Limitations
-**Spacing not configurable** — Spacing tokens (padding, gaps) use Tailwind defaults. Extend your Tailwind config manually for custom spacing in your codebase.
+**Spacing not configurable** â Spacing tokens (padding, gaps) use Tailwind defaults. Extend your Tailwind config manually for custom spacing in your codebase.
diff --git a/packages/docs/learn/theme/dark-mode.mdx b/packages/docs/learn/theme/dark-mode.mdx
new file mode 100644
index 00000000..311de776
--- /dev/null
+++ b/packages/docs/learn/theme/dark-mode.mdx
@@ -0,0 +1,32 @@
+---
+title: Dark mode
+description: Define light and dark color values for your theme.
+---
+
+import CliSyncAllCommand from "/snippets/cli-sync-all-command.mdx"
+
+Your theme supports light and dark color modes. When dark mode is enabled, each color token has separate light and dark values.
+
+## Adding dark mode
+
+1. Open **Theme** in the top navigation
+2. Click **Add dark mode** in the Colors section
+3. Edit the dark value for each color token
+
+{/* TODO: Add screenshot of dark mode color tokens */}
+
+Preview your designs in dark mode using the light/dark toggle in the toolbar.
+
+## Removing dark mode
+
+Click **Remove dark mode** in the Colors section. This deletes all dark color overrides.
+
+Removing dark mode is destructive. Use [version history](/learn/projects/version-history) to restore if needed.
+
+## Code export
+
+When dark mode is enabled, the CLI generates your color tokens as CSS variables. Light mode values load by default, and dark mode values activate when a `dark` class is present on the page. Run the CLI to sync:
+
+
+
+To add a dark mode toggle to your app, see the [Dark mode toggle](/guides/dark-mode) guide.
diff --git a/packages/docs/learn/theme/exporting-theme.mdx b/packages/docs/learn/theme/exporting-theme.mdx
index 97cb8f2d..206d452a 100644
--- a/packages/docs/learn/theme/exporting-theme.mdx
+++ b/packages/docs/learn/theme/exporting-theme.mdx
@@ -11,8 +11,8 @@ Your theme generates a Tailwind CSS configuration that your codebase uses for st
Click **Export** in the sidebar to view the generated Tailwind configuration for your theme. The dialog has two tabs:
-- **Tailwind CSS v3** — Shows a `tailwind.config.js` file with your tokens as a JavaScript module
-- **Tailwind CSS v4** — Shows a `theme.css` file with your tokens as CSS variables inside a `@theme` block
+- **Tailwind CSS v3** â Shows a `tailwind.config.js` file with your tokens as a JavaScript module
+- **Tailwind CSS v4** â Shows a `theme.css` file with your tokens as CSS variables inside a `@theme` block
Click **Copy to clipboard** to copy either format.
@@ -22,10 +22,10 @@ Click **Copy to clipboard** to copy either format.
The generated config includes colors, font sizes, font families, box shadows, border radius, container settings, and responsive breakpoints.
-When [dark mode](/guides/dark-mode) is enabled, the export includes additional dark mode overrides:
+When [dark mode](/learn/theme/dark-mode) is enabled, the export includes additional dark mode overrides:
-- **Tailwind v3** — An additional `theme.css` file with `:root` and `.dark` CSS variable blocks, and `darkMode: 'selector'` in the config
-- **Tailwind v4** — A `.dark` block and `@custom-variant dark` declaration in the `theme.css` file
+- **Tailwind v3** â An additional `theme.css` file with `:root` and `.dark` CSS variable blocks, and `darkMode: 'selector'` in the config
+- **Tailwind v4** â A `.dark` block and `@custom-variant dark` declaration in the `theme.css` file
## Sync to code