Theming
The shadcn-aligned semantic token surface and the base / brand-theme split. Rebrand with a single variable, or ship your own theme on top of the shared structural base.
@docmosaic/react reads every accent color, radius, and shadow from CSS custom properties - the same --background, --foreground, --primary, --secondary, --muted, --accent, --destructive, --border, --input, --ring, --radius every shadcn-based app already exposes. Rebrand the editor with the same variable an app uses for the rest of its UI.
No JavaScript-side theme provider, no runtime config - just CSS.
Mental model
The package ships its styles split into layers so you can swap colors without reinventing the structural defaults:
styles/base.css- brand-agnostic structural tokens (--editor-radius-section,--editor-shadow-section,--radius) and the cascade-layer order declaration.styles/themes/docmosaic.css- the DocMosaic brand colors as shadcn semantic tokens, including the bundled.darkscope. Default.styles/themes/minimal-light.css- shadcn-inspired neutral grays on a white surface.styles.css- convenience bundle that importsbase+ the DocMosaic brand theme.
All token values land in a @layer docmosaic cascade layer. base.css declares the layer order as docmosaic, base, components, utilities - so any consumer that already has a shadcn :root { --background: ... } block in @layer base (the default Tailwind @tailwind base layer) wins automatically.
You pick one of these layering patterns at import time:
1. Default DocMosaic look → import '@docmosaic/react/styles.css';
2. Custom theme on shared base → import '@docmosaic/react/styles/base.css';
import './my-theme.css';
3. Explicit DocMosaic theme → import '@docmosaic/react/styles/base.css';
import '@docmosaic/react/styles/themes/docmosaic.css';
4. Minimal light (shadcn-ish) → import '@docmosaic/react/styles/base.css';
import '@docmosaic/react/styles/themes/minimal-light.css';For dark mode, import styles.css (or themes/docmosaic.css) and toggle the .dark class on <html> - the theme ships a .dark scope. See the dark mode recipe.
Available themes
| Theme | Surface | Accent | Import path |
|---|---|---|---|
| DocMosaic | white | deep aubergine | @docmosaic/react/styles/themes/docmosaic.css (default) |
| Minimal Light | white | near-black | @docmosaic/react/styles/themes/minimal-light.css |
Token reference
Color tokens are stored as space-separated RGB triplets so they compose with the modern rgb(R G B / <alpha-value>) syntax that Tailwind v3 and modern CSS expect.
Semantic surface (shadcn-aligned)
| Token | Purpose | DocMosaic value |
|---|---|---|
--background | Editor canvas surround | 255 255 255 |
--foreground | Default text on --background | 56 29 42 (#381D2A) |
--card | Elevated surfaces - sidebars, inspector | 255 255 255 |
--card-foreground | Text on --card | 56 29 42 |
--primary | Primary accent - buttons, active borders | 56 29 42 |
--primary-foreground | Text/icons on --primary | 252 222 156 |
--secondary | Soft accent - hover states, subtle fills | 252 222 156 |
--secondary-foreground | Text on --secondary | 56 29 42 |
--muted | Placeholder / disabled background | 244 244 245 |
--muted-foreground | Placeholder / disabled text | 113 113 122 |
--accent | Selection highlight | 196 214 176 |
--accent-foreground | Text on --accent | 56 29 42 |
--destructive | Errors, destructive actions, warnings | 186 86 36 |
--destructive-foreground | Text on --destructive | 255 255 255 |
--border | Default border color | 228 228 231 |
--input | Input border color | 228 228 231 |
--ring | Focus ring | 56 29 42 |
--radius | Default border radius | 0.5rem |
Structural tokens
| Token | Purpose | Default |
|---|---|---|
--editor-radius-section | Border radius for image sections | 6px |
--editor-shadow-section | Shadow for image sections | 0 1px 3px rgba(0, 0, 0, 0.1) |
--radius | Default border radius | 0.5rem |
One-variable rebrand
The fastest path. Override --primary and let everything else inherit:
:root {
--primary: 79 70 229; /* indigo-600 */
--primary-foreground: 255 255 255;
}Every button, focus ring, and selected section reflects the new accent without touching the React tree.
Custom theme on shared base
For a full custom theme - every accent, surface, and border - supply the whole semantic surface:
import '@docmosaic/react/styles/base.css';
import './my-theme.css';/* my-theme.css */
:root {
--background: 250 250 252;
--foreground: 15 23 42;
--card: 255 255 255;
--card-foreground: 15 23 42;
--primary: 79 70 229;
--primary-foreground: 255 255 255;
--secondary: 224 231 255;
--secondary-foreground: 15 23 42;
--muted: 244 244 245;
--muted-foreground: 113 113 122;
--accent: 34 197 94;
--accent-foreground: 255 255 255;
--destructive: 220 38 38;
--destructive-foreground: 255 255 255;
--border: 228 228 231;
--input: 228 228 231;
--ring: 79 70 229;
--radius: 0.5rem;
}Dark mode
The bundled DocMosaic theme ships a .dark scope out of the box. Toggle the class on <html> (or any ancestor of the editor) and every semantic token flips.
With next-themes
The recommended pattern. attribute="class" toggles .dark on <html>, which the DocMosaic theme's .dark scope reads:
// 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>
);
}See the dark mode recipe for a full walkthrough with the toggle button.
See also
- Designer - how primitives consume these tokens
- Dark mode recipe - full setup