Layout
Introduction
Nest a <Layout> inside another <Layout>'s content or nested children to build composite
shells, e.g. an outer Layout with a page header/footer and an inner Layout
holding a sidenav rail.
Usage
Header + Content + Footer
With no sider, the parts stack in a single column.
import { Layout } from "../components/ui";
export default function MyPage() {
return (
<Layout
header={<SiteHeader />}
content={<Article />}
footer={<SiteFooter />}
/>
);
}
Header + Sider + Content
Passing sider wraps it and content in a row. siderWidth picks a rail
width (sm 14rem, md 16rem default, lg 18rem); siderHideBelow hides
the rail under a breakpoint for small screens.
import { Layout } from "../components/ui";
export default function MyPage() {
return (
<Layout
header={<SiteHeader />}
sider={<Sidenav />}
siderWidth="sm"
siderHideBelow="md"
content={<Article />}
/>
);
}
Sticky header and sider
stickyHeader pins the header to the top of the page scroll. stickySider
pins the sider below it and scrolls its own overflow — useful for a long
nav next to short content, or vice versa. fullHeight fills the viewport
for the outermost page shell.
import { Layout } from "../components/ui";
export default function DocsPage() {
return (
<Layout
fullHeight
stickyHeader
stickySider
header={<SiteHeader />}
sider={<DocsSidenav />}
siderHideBelow="md"
content={<Article />}
/>
);
}
Nested Layout
Nest a <Layout> inside content when the header/footer span the full
width but only part of the body needs a sider rail:
import { Layout } from "../components/ui";
export default function MyPage() {
return (
<Layout
header={<SiteHeader />}
content={
<Layout sider={<Sidenav />} content={<Article />} />
}
footer={<SiteFooter />}
/>
);
}
CMS Page Builder
This component is available as a layout block in the
Page Builder (content/pages/*.json). header,
sider, content, and footer are each a list of component blocks — any
block type works, including another layout for nested shells:
{
"type": "layout",
"siderWidth": "sm",
"siderHideBelow": "md",
"header": [
{ "type": "heading", "text": "Dashboard", "as": "h3", "size": "lg" }
],
"sider": [
{
"type": "stack",
"direction": "vertical",
"gap": "2",
"children": [
{ "type": "link", "text": "Overview", "href": "#" },
{ "type": "link", "text": "Reports", "href": "#" }
]
}
],
"content": [
{ "type": "text", "content": "Pick a page from the rail on the left." }
],
"footer": [
{ "type": "text", "size": "sm", "content": "© 2026 Acme" }
]
}
Leaving a part's list empty (or omitting it) skips that part's wrapper
element entirely — an untouched optional field like siderWidth/siderHideBelow
arrives as "" from the CMS and is treated as unset, falling back to the
component default.
Props
Layout
| Prop | Type | Description |
|---|---|---|
header | `string | JSX.Element` | Rendered inside a semantic <header> above the body. (Shorthand API only) |
sider | `string | JSX.Element` | Rendered inside a semantic <aside> rail. Its presence switches the body to a row of sider + content. (Shorthand API only) |
content | `string | JSX.Element` | Rendered inside a semantic <main>. children are appended after it. (Shorthand API only) |
footer | `string | JSX.Element` | Rendered inside a semantic <footer> below the body. (Shorthand API only) |
fullHeight | boolean | Fill the viewport height — for the outermost page shell. |
stickyHeader | boolean | Pin the header to the top of the page scroll. |
stickySider | boolean | Pin the sider below a sticky header; it scrolls internally. |
siderWidth | `"sm" | "md" | "lg"` | Sider rail width: sm (14rem), md (16rem, default), lg (18rem). |
siderHideBelow | `"sm" | "md" | "lg"` | Hide the sider under this breakpoint. Pair with an in-flow disclosure. |
hasSider | boolean | Manually force layout direction to row. (Compound API) |
headerClass | string | Extra class for the <header> part. (Shorthand API only) |
siderClass | string | Extra class for the <aside> part. (Shorthand API only) |
contentClass | string | Extra class for the <main> part. (Shorthand API only) |
footerClass | string | Extra class for the <footer> part. (Shorthand API only) |
bodyClass | string | Extra class for the row wrapper around sider + content (only rendered when sider is set). |
children | any | Children to render inside the layout shell. |
class | string | Custom CSS classes for the root element. |