| name | build-app-layout |
| description | Use this skill for any task involving app layouts — building new layouts, adding sidebars or navigation to existing apps, migrating an existing layout to mui-treasury components, or reviewing/improving layout structure. Trigger whenever the user mentions dashboard layout, sidebar navigation, app shell, header/footer/content structure, collapsible sidebar, drawer navigation, layout with sidebar, or asks to "build a layout", "add a sidebar", "set up the app layout", "review the layout". Also trigger when a mockup or design shows an app with sidebar + header + content regions, even if the user doesn't say "layout" explicitly. |
Installation
Components are installed via the mui-treasury CLI into src/mui-treasury/:
npx mui-treasury@latest add layout-core
npx mui-treasury@latest add sidebar
After installation, import from:
@/mui-treasury/layout/layout-core — layout components
@/mui-treasury/components/sidebar — sidebar primitives
Recommended Defaults
Use these as starting values unless the user specifies otherwise.
Collapsible EdgeSidebar
collapsedWidth: "52px"
SidebarIcon shrinkSize="20px" to center icons in the collapsed sidebar
permanentAutoCollapse="lg" to auto-collapse below the lg breakpoint
<EdgeSidebarCollapser render={<SidebarRail />} /> as a click-to-collapse trigger — SidebarRail is a pure visual component, EdgeSidebarCollapser injects the collapse onClick
- Use sidebar primitives for sidebar content — they auto-adapt to collapsed state
- left/right arrow icons for
EdgeSidebarCollapser
- down arrow icon for
CollapsibleIcon
EdgeSidebar Content Structure
Place SidebarContainer in the middle of EdgeSidebarContent so it grows to fill available space and becomes the scrollable area for menus. Static-height content (sidebar header/footer) should be siblings of SidebarContainer:
EdgeSidebarContent
├── Sidebar header (static) — e.g. app switcher, logged-in user, logo
├── SidebarContainer (flex: 1, scrollable) — navigation menus
└── Sidebar footer (static) — e.g. user preferences, settings, ads/banner
EdgeSidebarContent uses display: flex; flex-direction: column by default
SidebarContainer grows via flex: 1 and handles its own overflow scroll
- Sidebar header/footer keep their natural height and never scroll
- Sidebar primitives (
SidebarMenuButton, SidebarIcon, etc.) still work in the header/footer areas because they are descendants of EdgeSidebar — but collapse-aware CSS variables (--_collapsed/--_uncollapsed) only work inside SidebarContainer
SidebarMenuButton
-
should use the component prop for polymorphism, e.g. <SidebarMenuButton component="a" href="/dashboard"> or <SidebarMenuButton component={Link} to="/dashboard">
-
MUST be a child of SidebarMenuItem which is a child of SidebarMenuList. Never wrap SidebarMenuButton in a plain div or Box — the list structure (SidebarMenuList > SidebarMenuItem > SidebarMenuButton) is required for proper spacing, collapse behavior, and accessibility
-
Never use consecutive SidebarText siblings inside a SidebarMenuButton. For multi-line text, use a single SidebarText wrapping the content. For two-line text labels, use SidebarGroupText:
<SidebarMenuButton>
<Avatar />
<SidebarText><Typography>siriwatknp</Typography></SidebarText>
<SidebarText><Typography>admin@acme.com</Typography></SidebarText>
</SidebarMenuButton>
<SidebarMenuButton>
<Avatar />
<SidebarText>
<SidebarGroupText>
<Typography variant="body2">siriwatknp</Typography>
<Typography variant="caption">admin@acme.com</Typography>
</SidebarGroupText>
</SidebarText>
</SidebarMenuButton>
-
Never place secondary actions (e.g. IconButton, Badge) inside SidebarMenuButton. Use SidebarMenuAction as a sibling:
<SidebarMenuItem>
<SidebarMenuButton>
<Avatar />
<SidebarText>siriwatknp</SidebarText>
<Box sx={{ display: "flex", gap: 0.5 }}>
<IconButton size="small"><MoreHorizRounded /></IconButton>
<IconButton size="small"><NotificationsRounded /></IconButton>
</Box>
</SidebarMenuButton>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuButton>
<Avatar />
<SidebarText>siriwatknp</SidebarText>
</SidebarMenuButton>
<SidebarMenuAction>
<IconButton size="small"><MoreHorizRounded /></IconButton>
<IconButton size="small"><NotificationsRounded /></IconButton>
</SidebarMenuAction>
</SidebarMenuItem>
-
Never make SidebarMenuButton non-interactive (e.g. component="div" with cursor: "default"). If the element is not clickable, use SidebarMenuItem directly instead:
<SidebarMenuButton component="div" sx={{ cursor: "default", "&:hover": { bgcolor: "transparent" } }}>
<Avatar />
<SidebarText>siriwatknp</SidebarText>
</SidebarMenuButton>
<SidebarMenuItem>
<Avatar />
<SidebarText>siriwatknp</SidebarText>
</SidebarMenuItem>
-
SidebarMenuAction must only be used alongside a SidebarMenuButton sibling. If there is no SidebarMenuButton, use a plain IconButton instead
Rules of Thumb
-
Don't use hoverUncollapse with EdgeSidebarRail — they are noy designed to work together and can cause janky behavior
-
Don't use hoverUncollapse with SidebarTooltip — tooltips won't show when the sidebar is collapsed, so the hover state becomes inaccessible
-
It's recommended to have only one SidebarContainer as a direct child of EdgeSidebar — having multiple containers will cause the available space to split evenly, which mostly not the desired behavior.
-
Align icons in the center of the collapsed sidebar with proper shrinkSize on SidebarIcon.
-
Align custom elements like avatar in the center of the collapsed sidebar using negative margins with EdgeSidebar variables (see EdgeSidebar Collapsible Variables guide)
-
On pages that use EdgeDrawerTrigger but have no sidebar, add <EdgeSidebar variant={['permanent', { visibility: 'hidden' }]} /> to hide the trigger — permanent mode auto-hides EdgeDrawerTrigger, and visibility: 'hidden' prevents the sidebar from taking visual space
-
To create a floating sidebar (with margin, border, shadow, rounded corners), never apply these styles directly to EdgeSidebarContent — it breaks the layout. Instead, make EdgeSidebarContent transparent and style a child div:
<EdgeSidebarContent className="bg-transparent">
<div className="m-2 border shadow-xl rounded-lg bg-background flex flex-col">
{sidebar}
</div>
</EdgeSidebarContent>
Documentation
Read the relevant page based on your needs:
- Tutorials — Step-by-step lessons to build your first layout. Start here if unfamiliar with the layout system.
- Reference Guides — Complete API for all layout-core components and sidebar primitives with props tables.
- Explanation — Architecture decisions: CSS Grid + CSS variables, how collapse works, EdgeSidebar vs InsetSidebar, term mappings.
How-to Guides
Integration:
- Next.js Integration — Set up layout in App Router with layout.tsx/page.tsx split, MUI Treasury theme
Layout patterns:
Sidebar features:
Demos: