Customization
Jumbo React Vite is designed for deep customisation. This page covers theme configuration, layout defaults, the four independent theme regions (main, header, sidebar, footer), and the runtime Customizer drawer.
Theme configuration
All theme assembly happens in src/config/index.ts. It calls createJumboTheme() from
@jumbo/utilities/helpers with four separate MUI ThemeOptions objects — one per layout region:
// src/config/index.ts
import { createJumboTheme } from '@jumbo/utilities/helpers';
import { footerTheme } from '../themes/footer/default';
import { headerTheme } from '../themes/header/default';
import { mainTheme } from '../themes/main/default';
import { sidebarTheme } from '../themes/sidebar/default';
export const CONFIG = {
THEME: createJumboTheme(mainTheme, headerTheme, sidebarTheme, footerTheme),
};createJumboTheme() merges mainTheme as the base and overlays each region-specific theme on top,
so you only need to define the overrides in headerTheme, sidebarTheme, and footerTheme.
Editing the main theme
The primary brand colours, typography, and component defaults are set in
src/themes/main/default.ts:
// src/themes/main/default.ts (excerpt)
export const mainTheme = {
palette: {
mode: 'light',
primary: {
main: '#7352C7', // Brand purple — change this to match your brand
light: '#A07CDB',
dark: '#4E2F9E',
contrastText: '#FFF',
},
secondary: {
main: '#E44F55',
},
background: {
default: '#F5F7FA',
paper: '#FFFFFF',
},
},
typography: {
fontFamily: 'NoirPro, Arial',
h1: { fontSize: '1.5rem', fontWeight: 500 },
h2: { fontSize: '1.25rem', fontWeight: 500 },
},
shape: {
borderRadius: 8,
},
};Always reference MUI palette and typography tokens inside components instead of hardcoded hex values. This ensures light mode, semi-dark mode, and dark mode all respond correctly to a single theme change without per-component overrides.
Theme modes
Three pre-built modes are available. Each mode has corresponding files for all four regions:
| Mode | File path | Description |
|---|---|---|
| Light (default) | src/themes/main/default.ts | White background, brand purple primary |
| Semi-dark | src/themes/main/semi-dark.ts | Dark sidebar and header, light content area |
| Dark | src/themes/main/dark.ts | Full dark palette across all regions |
Switch modes at runtime using the Customizer drawer (see below), or change the default by
swapping the imports in src/config/index.ts:
// To default to dark mode, swap the imports:
import { mainTheme } from '../themes/main/dark';
import { headerTheme } from '../themes/header/dark';
import { sidebarTheme } from '../themes/sidebar/dark';
import { footerTheme } from '../themes/footer/dark';Layout configuration
The default layout configuration is defined in src/config/layouts/default.ts and consumed by
StretchedLayout. Every property accepts values from the @jumbo/utilities/constants enums:
// src/config/layouts/default.ts
const defaultLayoutConfig: LayoutOptions = {
sidebar: {
open: true,
hide: false,
variant: SIDEBAR_VARIANTS.PERSISTENT, // 'persistent' | 'temporary' | 'permanent'
style: SIDEBAR_STYLES.FULL_HEIGHT, // 'full-height' | 'clipped-under-header'
view: SIDEBAR_VIEWS.FULL, // 'full' | 'mini'
scrollType: SIDEBAR_SCROLL_TYPES.FIXED,
anchor: SIDEBAR_ANCHOR_POSITIONS.LEFT, // 'left' | 'right' | 'top' | 'bottom'
width: 240,
minWidth: 80,
drawerBreakpoint: 'xl',
},
header: {
hide: false,
fixed: true,
sx: { height: 80 },
drawerBreakpoint: 'xl',
},
footer: {
hide: false,
},
content: {
sx: { py: 4 },
},
};Layout config options
| Section | Key | Type | Description |
|---|---|---|---|
sidebar | variant | SIDEBAR_VARIANTS | persistent keeps sidebar mounted; temporary overlays it |
sidebar | view | SIDEBAR_VIEWS | full shows labels + icons; mini shows icons only |
sidebar | style | SIDEBAR_STYLES | full-height extends sidebar above header; clipped-under-header sits below |
sidebar | width | number | Expanded sidebar width in pixels (default 240) |
sidebar | minWidth | number | Collapsed/mini sidebar width in pixels (default 80) |
sidebar | drawerBreakpoint | MUI Breakpoint | Below this breakpoint, sidebar becomes a drawer overlay |
header | fixed | boolean | Whether the header sticks to the top on scroll |
header | sx.height | number | Header height in pixels (default 80) |
footer | hide | boolean | Set true to remove the footer entirely |
The Customizer drawer
The Customizer is a runtime settings panel that lets you switch themes, layout options, and locale without touching code. It appears as a floating button in the bottom-right corner of the app.
It is rendered by two components inside StretchedLayout:
// src/layouts/StretchedLayout/StretchedLayout.tsx (excerpt)
<JumboLayout header={<Header />} footer={<Footer />} sidebar={<Sidebar />}>
<Outlet />
<CustomizerSettings /> {/* Full settings drawer */}
<CustomizerButton /> {/* Floating toggle button */}
</JumboLayout>The Customizer persists sidebar state to a cookie (sidebar_state) so the chosen open/closed state
survives page refreshes.
Sidebar width constants
To change sidebar width globally, edit the values in src/config/layouts/default.ts:
sidebar: {
width: 280, // Expanded width — increase for wider labels
minWidth: 64, // Mini/collapsed width
}These values drive the content margin calculations inside JumboLayoutProvider automatically.