Overview
The SidebarLayout component is the default layout for Tailor Platform applications. It provides:
- Collapsible sidebar navigation
- Responsive mobile menu
- Dynamic breadcrumb navigation
- Theme toggle button
- Content outlet for page rendering
This component should be used as a direct child of AppShell.
Props
children
(props: { Outlet: () => React.ReactNode }) => React.ReactNode
Custom content renderer that receives an Outlet component for rendering page content.<SidebarLayout>
{({ Outlet }) => (
<>
<CustomHeader />
<Outlet />
<CustomFooter />
</>
)}
</SidebarLayout>
Custom sidebar component. Defaults to DefaultSidebar.<SidebarLayout sidebar={<MyCustomSidebar />} />
Features
Responsive Behavior
- Desktop: Sidebar is visible and collapsible
- Mobile: Sidebar slides in as an overlay (offcanvas)
- Icon Mode: Sidebar collapses to icon-only mode on narrow screens
The header includes:
- Sidebar toggle button (hidden when sidebar is open on desktop)
- Dynamic breadcrumb navigation
- Theme toggle button (light/dark mode)
Content Area
The content area automatically renders:
- Page components from your route configuration
- Custom content via the
children render prop
Usage Examples
Basic Usage
Simplest setup with all defaults:
import { AppShell, SidebarLayout } from "@tailor-platform/app-shell";
const App = () => (
<AppShell title="My App">
<SidebarLayout />
</AppShell>
);
Custom Content Wrapper
Wrap page content with custom elements:
import { AppShell, SidebarLayout } from "@tailor-platform/app-shell";
const App = () => (
<AppShell title="My App">
<SidebarLayout>
{({ Outlet }) => (
<div className="custom-wrapper">
<div className="page-header">
<h1>Custom Header</h1>
</div>
<main className="page-content">
<Outlet />
</main>
<footer className="page-footer">
<p>© 2024 My Company</p>
</footer>
</div>
)}
</SidebarLayout>
</AppShell>
);
Replace the default sidebar with your own:
import { AppShell, SidebarLayout } from "@tailor-platform/app-shell";
import { MySidebar } from "./components/MySidebar";
const App = () => (
<AppShell title="My App">
<SidebarLayout sidebar={<MySidebar />} />
</AppShell>
);
import {
AppShell,
SidebarLayout,
DefaultSidebar
} from "@tailor-platform/app-shell";
const SidebarHeader = () => (
<div className="p-4">
<img src="/logo.svg" alt="Logo" />
<h1>My App</h1>
</div>
);
const SidebarFooter = () => (
<div className="p-4 border-t">
<p className="text-sm">Version 1.0.0</p>
</div>
);
const App = () => (
<AppShell title="My App">
<SidebarLayout
sidebar={
<DefaultSidebar
header={<SidebarHeader />}
footer={<SidebarFooter />}
/>
}
/>
</AppShell>
);
With Multiple Layout Sections
import { AppShell, SidebarLayout } from "@tailor-platform/app-shell";
const App = () => (
<AppShell title="My App">
<SidebarLayout>
{({ Outlet }) => (
<div className="layout-container">
<aside className="left-panel">
<QuickActions />
</aside>
<main className="main-content">
<Outlet />
</main>
<aside className="right-panel">
<Notifications />
</aside>
</div>
)}
</SidebarLayout>
</AppShell>
);
The DefaultSidebar component provides auto-generated navigation from your module configuration.
Props
Custom header content displayed at the top of the sidebar
Custom footer content displayed at the bottom of the sidebar
When provided, enables explicit sidebar composition using SidebarItem, SidebarGroup, and other components. Auto-generation is completely disabled when children is specified.
Auto-generation Mode
By default, DefaultSidebar automatically generates navigation items based on your module/resource definitions:
import { DefaultSidebar } from "@tailor-platform/app-shell";
// Automatically generates nav items from modules
<DefaultSidebar />
Composition Mode
Manually define sidebar structure using components:
import {
DefaultSidebar,
SidebarItem,
SidebarGroup,
SidebarSeparator
} from "@tailor-platform/app-shell";
<DefaultSidebar>
<SidebarItem to="/dashboard" />
<SidebarGroup title="Products">
<SidebarItem to="/products/all" />
<SidebarItem to="/products/categories" />
</SidebarGroup>
<SidebarSeparator />
<SidebarItem to="/settings" />
</DefaultSidebar>
When using composition mode, you can use these components:
Renders a navigation link with automatic active state and icon/title from page metadata.
<SidebarItem to="/dashboard" />
Groups related navigation items together:
<SidebarGroup title="Products">
<SidebarItem to="/products/all" />
<SidebarItem to="/products/new" />
</SidebarGroup>
Adds a visual divider between sidebar sections:
<SidebarItem to="/dashboard" />
<SidebarSeparator />
<SidebarItem to="/settings" />
Customization
Theme Toggle
The theme toggle button is built-in and uses the useTheme hook:
import { useTheme } from "@tailor-platform/app-shell";
const CustomThemeToggle = () => {
const { theme, setTheme } = useTheme();
return (
<button onClick={() => setTheme(theme === "dark" ? "light" : "dark")}>
Toggle Theme
</button>
);
};
Breadcrumb Navigation
The breadcrumb is dynamically generated from your current route. Customize breadcrumb titles using meta.breadcrumbTitle in your module/resource definitions:
import { defineResource } from "@tailor-platform/app-shell";
defineResource({
path: ":productId",
meta: {
title: "Product Details",
breadcrumbTitle: (productId) => `Product ${productId}`
},
component: ProductDetails
});
Access sidebar state in custom components:
import { useSidebar } from "@tailor-platform/app-shell";
const CustomComponent = () => {
const { open, isIconMode } = useSidebar();
return (
<div>
Sidebar is {open ? 'open' : 'closed'}
{isIconMode && <span>(Icon mode)</span>}
</div>
);
};
TypeScript
type SidebarLayoutProps = {
children?: (props: { Outlet: () => React.ReactNode }) => React.ReactNode;
sidebar?: React.ReactNode;
};
type DefaultSidebarProps = {
header?: React.ReactNode;
footer?: React.ReactNode;
children?: React.ReactNode;
};
Styling
The sidebar uses Tailwind CSS with the astw: prefix. Customize the appearance by:
- Override CSS variables in your theme
- Apply custom classes to wrapper components
- Use the
className prop on custom sidebar components
/* Custom sidebar styling */
:root {
--sidebar-width: 280px;
--sidebar-background: hsl(0 0% 98%);
}
.dark {
--sidebar-background: hsl(0 0% 10%);
}
See Also