Recipes
Dark mode
Wire the bundled .dark scope to next-themes (or any class toggle) and the editor follows along.
The DocMosaic theme ships a .dark scope out of the box. Every semantic token (--background, --foreground, --primary, …) flips when the .dark class lands on <html> (or any ancestor of the editor). Pair it with next-themes and you're done.
Install
bun add next-themesWire next-themes at the root
// app/layout.tsx
import { ThemeProvider } from 'next-themes';
import '@docmosaic/react/styles.css';
export default function Layout({ children }: { children: React.ReactNode }) {
return (
<html lang="en" suppressHydrationWarning>
<body>
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
{children}
</ThemeProvider>
</body>
</html>
);
}The key bits:
attribute="class"-next-themesadds thedarkclass to<html>, which the DocMosaic theme's.darkscope reads.suppressHydrationWarning- required bynext-themesto avoid the class-mismatch warning on first paint.enableSystem- respects the user's OS preference by default.
Toggle button
'use client';
import { useTheme } from 'next-themes';
import { Moon, Sun } from 'lucide-react';
export function ThemeToggle() {
const { resolvedTheme, setTheme } = useTheme();
return (
<button onClick={() => setTheme(resolvedTheme === 'dark' ? 'light' : 'dark')}>
{resolvedTheme === 'dark' ? <Sun /> : <Moon />}
</button>
);
}Custom selector
Prefer prefers-color-scheme or a data-theme attribute? Mirror the brand dark palette under your selector. The token names are identical to the .dark scope shipped by themes/docmosaic.css - copy them in.
@media (prefers-color-scheme: dark) {
:root {
--background: 13 8 11;
--foreground: 252 222 156;
/* ... */
}
}No JS toggle needed. The editor reads the variables on every paint.
See also
- Theming - the full token surface