Layouts
Layouts in Sapling provide a way to create consistent page structures and share common elements across multiple pages.
Basic Layout
A basic layout in Sapling is a TypeScript function that wraps your page content. Here's a simple example:
import { Layout as SaplingLayout, html, type LayoutProps } from "@sapling/sapling";
export type BaseLayoutProps = LayoutProps & {
title?: string;
description?: string;
};
export default async function Layout(props: BaseLayoutProps) {
return await SaplingLayout({
head: html`
<title>${props.title}</title>
<meta name="description" content="${props.description}" />
`,
children: html`
<div>
${props.children}
</div>
`
});
}
Layout Properties
Layouts accept properties that extend Sapling's base LayoutProps
:
type LayoutProps = {
head?: unknown; // Additional head content
bodyClass?: string; // Classes to apply to the body
children?: unknown; // Page content
unoConfig?: unknown; // UnoCSS configuration
};
Using Components in Layouts
Layouts can import and use components to create consistent page structures:
import { Nav } from "../components/Nav.ts";
import { Footer } from "../components/Footer.ts";
export default async function Layout(props: BaseLayoutProps) {
return await SaplingLayout({
// ... other props
children: html`
<div class="relative z-10">
${Nav()}
${props.children}
${Footer()}
</div>
`
});
}
Styling with UnoCSS
Sapling layouts can include UnoCSS configuration for consistent styling:
import { config } from "../uno.config.ts";
export default async function Layout(props: BaseLayoutProps) {
return await SaplingLayout({
unoConfig: config,
bodyClass: `font-sans @dark:bg-black @dark:text-white ${props.bodyClass ?? ''}`,
// ... other props
});
}
Nested Layouts
You can create specialized layouts that extend your base layout:
import BaseLayout from "./Layout.ts";
export default async function DocsLayout(props: DocsLayoutProps) {
return await BaseLayout({
...props,
children: html`
<div class="docs-container">
<aside>${props.leftNav}</aside>
<main>${props.children}</main>
<aside>${props.tableOfContents}</aside>
</div>
`
});
}
Using Layouts in Pages
To use a layout in a page component:
import Layout from "../layouts/Layout.ts";
export default async function HomePage() {
return await Layout({
title: "Home - My Site",
description: "Welcome to my website",
children: html`
<main class="p-4">
<h1>Welcome!</h1>
</main>
`
});
}
Best Practices
- Type Safety: Define proper TypeScript interfaces for your layout props
- Modularity: Break down layouts into reusable components
- Flexibility: Make layouts adaptable with optional props
- Dark Mode: Include dark mode support using the
@dark:
prefix - Performance: Keep layouts lightweight and avoid unnecessary nesting