Layouts
Jumbo React Vite ships eight layout variants. Each is a React component that composes
JumboLayoutProvider + JumboLayout with a specific configuration. The active layout is
determined solely by which route the user is on.
How layouts work
Every layout follows this pattern:
JumboLayoutProvider— supplies an initialLayoutOptionsconfig and owns the layout stateJumboLayout— renders the shell usingheader,sidebar,footer, andrightSidebarslots<Outlet />— renders the matched page route inside the content area
// Pattern used by every layout variant
export function ExampleLayout() {
return (
<JumboLayoutProvider layoutConfig={myLayoutConfig}>
<JumboLayout header={<Header />} footer={<Footer />} sidebar={<Sidebar />}>
<Outlet />
</JumboLayout>
</JumboLayoutProvider>
);
}Layout variants
| Layout | Route prefix | Sidebar | Header | Footer | Notes |
|---|---|---|---|---|---|
StretchedLayout | / | Persistent, 240px | Fixed, 80px | Visible | Default layout; includes Customizer |
Demo1Layout | /demo-1 | None (hide: true) | Fixed, 100px | Visible | Header-only navigation |
Demo2Layout | /demo-2 | Temporary (drawer) | spreadOut | Visible | Mobile-style overlay sidebar |
Demo3Layout | /demo-3 | Persistent | Fixed | Hidden | Right sidebar region enabled |
Demo4Layout | /demo-4 | Persistent | Fixed | Hidden | Demo3 variant with a HeroSection banner |
SoloLayout | /auth, /extra-pages | None | None | None | Minimal shell for auth and error pages |
SettingsLayout | /user/settings/* | None | None | None | Nested layout for settings subtree |
NewLayout1 | /new-layout | Custom | Custom | Custom | Extensible scaffold for new layouts |
StretchedLayout (default)
The application default. Mounts the Customizer settings drawer and a redirect from / to
/dashboards/misc.
// src/layouts/StretchedLayout/StretchedLayout.tsx
export function StretchedLayout() {
const location = useLocation();
return (
<JumboLayoutProvider layoutConfig={defaultLayoutConfig}>
<JumboLayout
header={<Header />}
footer={<Footer />}
sidebar={<Sidebar menus={getMenus()} />}
>
{location.pathname === '/' && <Navigate to='/dashboards/misc' />}
<Outlet />
<CustomizerSettings />
<CustomizerButton />
</JumboLayout>
</JumboLayoutProvider>
);
}SoloLayout
Minimal layout with no navigation. Used for /auth and /extra-pages routes.
// src/layouts/SoloLayout/SoloLayout.tsx
export function SoloLayout() {
return (
<JumboLayoutProvider layoutConfig={{ /* all regions hidden */ }}>
<Outlet />
</JumboLayoutProvider>
);
}Sidebar variants in detail
The sidebar behavior is controlled by the variant and view options in LayoutOptions.sidebar:
| Variant | Behavior |
|---|---|
SIDEBAR_VARIANTS.PERSISTENT | Sidebar stays mounted and pushes page content when open/closed |
SIDEBAR_VARIANTS.TEMPORARY | Overlay drawer that closes on outside click (Demo2Layout) |
SIDEBAR_VARIANTS.PERMANENT | Always visible; cannot be toggled |
| View | Behavior |
|---|---|
SIDEBAR_VIEWS.FULL | Full sidebar showing icons + text labels |
SIDEBAR_VIEWS.MINI | Collapsed sidebar showing icons only (80px wide) |
Toggle the view at runtime using useJumboLayout().setSidebarOptions().
Creating a new layout
Create the layout directory and files
src/layouts/MyLayout/ MyLayout.tsx Header.tsx Sidebar.tsx menus.ts index.tsDefine a layout config
typescript// src/layouts/MyLayout/_config.ts import { SIDEBAR_VARIANTS, SIDEBAR_VIEWS } from '@jumbo/utilities/constants'; import type { LayoutOptions } from '@jumbo/types'; export const myLayoutConfig: LayoutOptions = { sidebar: { variant: SIDEBAR_VARIANTS.PERSISTENT, view: SIDEBAR_VIEWS.FULL, width: 260, minWidth: 64, drawerBreakpoint: 'lg', }, header: { fixed: true, sx: { height: 72 } }, footer: { hide: true }, root: {}, content: { sx: { py: 3 } }, wrapper: {}, main: {}, };Build the layout component
tsx// src/layouts/MyLayout/MyLayout.tsx import { JumboLayout, JumboLayoutProvider } from '@jumbo/components'; import { Outlet } from 'react-router-dom'; import { myLayoutConfig } from './_config'; import { Header } from './Header'; import { Sidebar } from './Sidebar'; import { getMenus } from './menus'; export function MyLayout() { return ( <JumboLayoutProvider layoutConfig={myLayoutConfig}> <JumboLayout header={<Header />} sidebar={<Sidebar menus={getMenus()} />}> <Outlet /> </JumboLayout> </JumboLayoutProvider> ); }Register the route
typescript// src/routes/index.tsx import { MyLayout } from '@/layouts/MyLayout'; // Add to the routes array: { path: '/my-layout', element: <MyLayout />, children: generateChildRoutes(demoRoutes, '/my-layout'), },
Pass any of the existing route arrays (demoRoutes, demo2Routes, etc.) as the children of
your new layout. This gives you all pre-built pages instantly without duplicating route
definitions.