React
How to build a dashboard shell in React
A dashboard shell in React is a persistent sidebar, a header and one scrolling content area. Here is the structure, the block to start from and the states.
Key points
- The shell keeps sidebar, header and content outside the route: only the content changes.
- Start from dashboard-01 for a full reference, from sidebar-07 if you only want structure.
- Read the sidebar open/closed state before the first paint, or the user sees a jump.
A dashboard shell in React has three stable regions: a sidebar that stays mounted, a header that says where you are, and a content area that scrolls on its own. Everything else is content, not structure.
When a shell breaks, there is usually one cause: the structure lives inside the page. Change route, React unmounts the sidebar and header, and the user sees a white flash on every click.
The three regions, in order of importance
- Sidebar: 240 to 280px, collapsing to icons below 1024px.
- Header: breadcrumb and actions for the current page, not for the shell.
- Content: one element with overflow-auto; the body must not scroll.
- Sidebar state: a cookie read on the server, so the first paint is already correct.
- Mobile: the sidebar becomes a Sheet, not a panel that pushes the content.
What to take from the catalogue
The shadcn/ui block dashboard-01 is the full reference: sidebar, cards, chart and table. For a lighter shell start from sidebar-07, which collapses to icons, and browse the dashboard category for variants. Source: github.com/shadcn-ui/ui, MIT licence.
The minimum structure
npx shadcn@latest add sidebar breadcrumb separator
import type { ReactNode } from "react";
import { SidebarInset, SidebarProvider, SidebarTrigger } from "@/components/ui/sidebar";
export function DashboardShell({ sidebar, children }: { sidebar: ReactNode; children: ReactNode }) {
return (
{sidebar}
Workspace
{children}
);
}
A concrete example: who scrolls
.shell { display: grid; grid-template-columns: auto 1fr; height: 100dvh; }
.shell > main { min-height: 0; overflow: auto; }
The line that breaks the layout when missing is min-height: 0. A grid child starts with min-height: auto, so it grows with its content and pushes the height past the viewport; with the line, main scrolls alone and sidebar and header stay put. 100dvh avoids the address-bar jump on mobile.
In the catalogue, read on 1 November 2026 from data/blocks.json (snapshot of 31 October 2026), the dashboard category holds 20 blocks from 3 sources and 17 come from shadcn-ui-ui. In the same file dashboard-01 declares 7 npm dependencies and 19 registryDependencies, while sidebar-07 declares 0 and 6.
The three states the shell must handle
Loading: a skeleton with fixed height, so the content does not jump when it arrives. Empty: the shell stays, only the middle area changes. Error: a message inside the content area with a retry button; the sidebar must not vanish because one fetch failed.
Stated limitation: dashboard-01 pulls in @dnd-kit, @tanstack/react-table, zod and @tabler/icons-react. If your dashboard has no sortable tables, that dependency is dead weight: take sidebar-07 and build the cards yourself.
The decision rule
Take dashboard-01 only if you need the sortable table and the chart together. If one of the two is missing, start from sidebar-07 and add the pieces: the difference is seven npm dependencies against zero, and each one needs upgrading. A single missing feature does not justify the whole block.
The mistake to avoid
Putting overflow-auto on the body and on the content area too: two scrollbars appear, the header loses its fixed position, and on iOS the bounce moves the entire page. Let one element scroll, with overflow: hidden on the body and height: 100dvh on the shell.
Below 1024px the sidebar becomes an overlay panel with one closing point: the header button and the Esc key must do the same thing, and focus returns to the button when the panel closes. If the panel pushes the content, every open resets the scroll position.
To fill the sections, read the 5 blocks for an admin dashboard page guide and the measured comparison Best dashboard blocks 2026. Before you install the primitives, read Radix vs Base UI vs React Aria.
Frequently asked questions
How much code does a dashboard shell need?
Very little: a provider, a sidebar and one scrolling area. The real work sits in the sidebar state and the content, not in the layout.
Fixed sidebar or collapsible?
Collapsible to icons below 1024px, because at that width the content loses more space than the navigation gains.
Where should the open/closed sidebar state live?
In a cookie read on the server, so the first paint is already correct. localStorage only works for a fully client-side app.
Can I use dashboard-01 in a commercial project?
Yes, shadcn/ui is MIT and the code is copied into your repository. Check the dependencies the block brings with it.
Should the shell handle loading?
Yes, with a skeleton of fixed height. If the height changes when data arrives, every navigation produces a layout shift.