🎨 Theming Nodeblocks Components
Customize the look and feel of all Nodeblocks components with a unified MUI-based theme system 🎭
This guide covers how to use the @nodeblocks/frontend-theme package to create consistent, branded experiences across your application.
📋 Overview
The Nodeblocks theme package provides:
- Pre-configured MUI Theme – A ready-to-use Material-UI theme with optimized defaults
- ThemeProvider Component – Easy theme application across your app
- Customizable Tokens – Palette, typography, spacing, and component styles
- CSS Variables Support – Modern CSS custom properties for runtime theming
- Global Styles – Consistent styling for common UI patterns
🎯 Key Benefit: When wrapped with
ThemeProvider, you can use any MUI component (Button, Tabs, TextField, Card, etc.) alongside Nodeblocks components – they'll all share the same consistent styling. Mix and match freely!
When to Use What
| Scenario | Approach |
|---|---|
| Using Nodeblocks components as-is | Just wrap with <ThemeProvider> |
| Changing brand colors only | Pass custom palette to ThemeProvider |
| Full brand customization | Create theme with createTheme() |
📦 Installation
# Install the theme package
npm install @nodeblocks/frontend-theme
# Required peer dependencies (if not already installed)
npm install @mui/material @emotion/react @emotion/styled
🚀 Quick Start
Basic Usage
Wrap your application with the ThemeProvider to apply the default Nodeblocks theme:
import React from 'react';
import { ThemeProvider } from '@nodeblocks/frontend-theme';
import { SignIn } from '@nodeblocks/frontend-signin-block';
import { Navbar } from '@nodeblocks/frontend-navbar-block';
function App() {
return (
<ThemeProvider>
<Navbar
leftContent={<span>My App</span>}
centerContent={<nav>Navigation</nav>}
rightContent={<button>Login</button>}
/>
<main>
<SignIn onSubmit={(data) => console.log(data)} />
</main>
</ThemeProvider>
);
}
export default App;
ThemeProvider Props
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | - | Your application components |
theme | Theme | defaultTheme | Custom MUI theme object |
enableCssBaseline | boolean | true | Apply CSS reset and baseline styles |
injectMuiStylesFirst | boolean | true | Inject MUI styles first for easier overrides |
Using MUI Components with Nodeblocks
Any MUI component works seamlessly inside ThemeProvider:
import { ThemeProvider } from '@nodeblocks/frontend-theme';
import { ListUsers } from '@nodeblocks/frontend-list-users-block';
import { Button, Tabs, Tab, TextField, Card } from '@mui/material';
function App() {
return (
<ThemeProvider>
{/* MUI components - automatically styled */}
<Card sx={{ p: 2, mb: 2 }}>
<TextField label="Search users" size="small" />
<Button variant="contained">Search</Button>
</Card>
<Tabs value={0}>
<Tab label="Active" />
<Tab label="Pending" />
</Tabs>
{/* Nodeblocks components - same consistent styling */}
<ListUsers data={users} />
</ThemeProvider>
);
}
🎨 Color Palette
The theme includes a comprehensive color palette designed for modern applications.
Default Colors
import { palette } from '@nodeblocks/frontend-theme';
// Primary colors
palette.primary.main // #006ead - Primary brand color
palette.primary.light // #0391d4 - Lighter variant
palette.primary.dark // #004e8b - Darker variant
// Secondary colors (greys)
palette.secondary.main // #737d90 - Secondary actions
palette.secondary.light // #9ea4b1 - Light secondary
palette.secondary.dark // #1d1e20 - Dark secondary
// Semantic colors
palette.error.main // #e54e4b - Error states
palette.warning.main // #ed6c02 - Warning states
palette.success.main // #2e7d32 - Success states
palette.info.main // #006ead - Info states
// Grey scale
palette.grey[25] // #f8f8f8 - Lightest grey
palette.grey[50] // #f3f3f3
palette.grey[100] // #c9d0da
palette.grey[500] // #737d90 - Mid grey
palette.grey[900] // #1d1e20 - Darkest grey
// Background & Surface
palette.background.default // #f3f3f3 - Page background
palette.background.paper // #ffffff - Card/paper background
// Text colors
palette.text.primary // #1d1e20 - Primary text
palette.text.secondary // #737d90 - Secondary text
palette.text.disabled // #9ea4b1 - Disabled text
// Surface & Divider
palette.surface.accentLightLow // #EBF7FF - Light accent surface
palette.divider // #e2e4e7 - Border/divider color
Customizing Colors
import { createTheme } from '@mui/material';
import { ThemeProvider, defaultTheme } from '@nodeblocks/frontend-theme';
// Create a custom theme - defaultTheme as base preserves all Nodeblocks defaults
const customTheme = createTheme(defaultTheme, {
palette: {
primary: {
main: '#8B5CF6', // Purple brand color
light: '#A78BFA',
dark: '#7C3AED',
},
secondary: {
main: '#EC4899', // Pink accent
light: '#F472B6',
dark: '#DB2777',
},
},
});
function App() {
return (
<ThemeProvider theme={customTheme}>
{/* Your app with custom colors */}
</ThemeProvider>
);
}
💡 Important: Using
createTheme(defaultTheme, { ... })deep-merges your changes with Nodeblocks defaults, preserving typography, spacing, and component styles.
✍️ Typography
The theme includes a complete typography system:
Default Typography Scale
import { typography } from '@nodeblocks/frontend-theme';
// Headings
typography.h1 // 2.5rem, weight 700
typography.h2 // 2rem, weight 700
typography.h3 // 1.75rem, weight 600
typography.h4 // 1.5rem, weight 600
typography.h5 // 1.25rem, weight 600
typography.h6 // 1.125rem, weight 600
// Body text
typography.body1 // 1rem, weight 400
typography.body2 // 0.875rem, weight 400
// Subtitles
typography.subtitle1 // 1rem, weight 500
typography.subtitle2 // 0.875rem, weight 500
// Other variants
typography.button // 0.875rem, weight 600
typography.caption // 0.75rem, weight 400
typography.overline // 0.75rem, weight 500, uppercase
Default Font Stack
The theme uses a cross-platform font stack optimized for Japanese and Western characters:
fontFamily: [
'Hiragino Sans', // macOS Japanese
'ヒラギノ角ゴ ProN W3', // macOS Japanese (alternate)
'Hiragino Kaku Gothic ProN',
'Hiragino Kaku Gothic Pro',
'-apple-system', // macOS/iOS system font
'BlinkMacSystemFont', // Chrome on macOS
'Segoe UI', // Windows
'Roboto', // Android/Chrome OS
'Yu Gothic', // Windows Japanese
'Meiryo', // Windows Japanese (legacy)
'sans-serif',
].join(',')
Note: For Western-only apps, consider replacing with
'"Inter", "Helvetica Neue", sans-serif'.
Customizing Typography
import { createTheme } from '@mui/material';
import { ThemeProvider, defaultTheme } from '@nodeblocks/frontend-theme';
const customTheme = createTheme(defaultTheme, {
typography: {
fontFamily: '"Inter", "Helvetica Neue", sans-serif',
h1: {
fontSize: '3rem',
fontWeight: 800,
},
button: {
fontWeight: 700,
letterSpacing: '0.05em',
},
},
});
function App() {
return (
<ThemeProvider theme={customTheme}>
{/* Your app with custom typography */}
</ThemeProvider>
);
}
📐 Spacing & Border Radius
The theme provides consistent spacing, border radius, and responsive breakpoints.
Spacing System
The theme uses an 8px base spacing unit:
import { spacing } from '@nodeblocks/frontend-theme';
// spacing = 8 (base unit in pixels)
// Usage in theme.spacing()
theme.spacing(1) // 8px
theme.spacing(2) // 16px
theme.spacing(3) // 24px
theme.spacing(4) // 32px
Border Radius
The default theme uses a base border radius of 4px:
// In the default theme:
// shape.borderRadius = 4 (base unit in pixels)
// Components typically use multiples:
// Buttons, inputs: borderRadius * 2 = 8px
// Cards: borderRadius * 3 = 12px
Breakpoints
The theme uses custom responsive breakpoints:
breakpoints: {
values: {
xs: 0, // Extra small devices
sm: 600, // Small devices
md: 900, // Medium devices
lg: 1024, // Large devices (custom: MUI default is 1200)
xl: 1536, // Extra large devices
},
}
Note: The
lgbreakpoint is set to1024pxinstead of MUI's default1200px.
Customizing Spacing & Shape
import { createTheme } from '@mui/material';
import { ThemeProvider, defaultTheme } from '@nodeblocks/frontend-theme';
const customTheme = createTheme(defaultTheme, {
spacing: 4, // Change base unit to 4px (theme.spacing(2) = 8px)
shape: {
borderRadius: 8, // Rounder corners (default is 4)
},
});
function App() {
return (
<ThemeProvider theme={customTheme}>
{/* Your app with custom spacing */}
</ThemeProvider>
);
}
🧩 Component Overrides
Override MUI component styles to match your brand's design system.
Customizing Components
import { createTheme } from '@mui/material';
import { ThemeProvider, defaultTheme } from '@nodeblocks/frontend-theme';
const customTheme = createTheme(defaultTheme, {
components: {
MuiButton: {
styleOverrides: {
root: {
borderRadius: 20, // Pill-shaped buttons
textTransform: 'none',
},
},
},
},
});
function App() {
return (
<ThemeProvider theme={customTheme}>
{/* Your app with custom components */}
</ThemeProvider>
);
}
🔧 Advanced Usage
Using the useTheme Hook
Access theme values in your components:
import { useTheme } from '@nodeblocks/frontend-theme';
function MyComponent() {
const theme = useTheme();
return (
<div style={{
backgroundColor: theme.palette.background.paper,
padding: theme.spacing(2),
borderRadius: theme.shape.borderRadius * 2,
color: theme.palette.text.primary,
}}>
Themed content
</div>
);
}
Using CSS Variables
The theme enables CSS variables by default. Use them in custom CSS:
.my-custom-element {
color: var(--mui-palette-primary-main);
background: var(--mui-palette-background-paper);
padding: calc(var(--mui-spacing) * 2); /* 16px */
}
Using the Default Theme Directly
You can access the pre-configured theme object for inspection or extension:
import { createTheme } from '@mui/material';
import { defaultTheme } from '@nodeblocks/frontend-theme';
// Inspect theme values
console.log(defaultTheme.palette.primary.main); // #006ead
console.log(defaultTheme.spacing(2)); // 16
console.log(defaultTheme.shape.borderRadius); // 4
// Use as base for custom theme
const extendedTheme = createTheme(defaultTheme, {
palette: {
primary: {
main: '#your-color',
},
},
});
🌙 Dark Mode
The default theme is light mode only. To add dark mode support:
import { createTheme } from '@mui/material';
import { ThemeProvider, defaultTheme } from '@nodeblocks/frontend-theme';
const darkTheme = createTheme(defaultTheme, {
palette: {
mode: 'dark',
background: { default: '#121212', paper: '#1e1e1e' },
text: { primary: '#ffffff', secondary: '#b0b0b0' },
},
});
function App() {
return (
<ThemeProvider theme={darkTheme}>
{/* Your app with dark mode */}
</ThemeProvider>
);
}
❓ Troubleshooting
| Issue | Solution |
|---|---|
| Theme not applying | Ensure ThemeProvider wraps your entire app at the root level |
| Styles being overridden | Set injectMuiStylesFirst={true} (default) on ThemeProvider |
| TypeScript errors with custom palette | Extend the MUI theme types (see MUI docs) |
| Components look unstyled | Check that @mui/material peer dependency is installed |
🔗 Related Resources
- MUI Theming Documentation
- MUI Palette Customization
- MUI Component Overrides
- Scratch Setup Guide
- Advanced Usage Guide
Build beautiful, consistent UIs with Nodeblocks theming ✨