Skip to main content

🎨 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

ScenarioApproach
Using Nodeblocks components as-isJust wrap with <ThemeProvider>
Changing brand colors onlyPass custom palette to ThemeProvider
Full brand customizationCreate 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

PropTypeDefaultDescription
childrenReactNode-Your application components
themeThemedefaultThemeCustom MUI theme object
enableCssBaselinebooleantrueApply CSS reset and baseline styles
injectMuiStylesFirstbooleantrueInject 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 lg breakpoint is set to 1024px instead of MUI's default 1200px.

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

IssueSolution
Theme not applyingEnsure ThemeProvider wraps your entire app at the root level
Styles being overriddenSet injectMuiStylesFirst={true} (default) on ThemeProvider
TypeScript errors with custom paletteExtend the MUI theme types (see MUI docs)
Components look unstyledCheck that @mui/material peer dependency is installed


Build beautiful, consistent UIs with Nodeblocks theming