Skip to main content

PageLayout

    The PageLayout component provides the basic layout for your app with slots for a header, sidebar, main content, and a details panel.

    Experimental

    PageLayout is still experimental. Be aware that the API is subject to change. See Strato versioning for details.

    Import

    import { _PageLayout } from '@dynatrace/strato-components/layouts';

    Defaults

    All panels work without configuration. The defaults below are applied when you do not set a prop explicitly.

    SlotminWidthmaxWidthdefaultWidthdefaultLayoutbreakpoint
    PageLayout.Sidebar200'50%''15%'n/a960
    PageLayout.Details320'50%''25%''split'600

    Demo

    CodeSandbox

    Responsive behavior

    Below its configured breakpoint, a panel collapses into a Drawer to preserve screen space.

    Layout hierarchy

    PageLayout.Sidebar and PageLayout.Details each have a breakpoint prop, but they measure different widths:

    • PageLayout.Sidebar - breakpoint is measured against the full PageLayout container width.
    • PageLayout.Details - breakpoint is measured against the combined width of the Content + Details area, to the right of the sidebar.

    This means the two breakpoints fire independently. When the sidebar is expanded, it consumes page width and shrinks the content+details area. A details panel with breakpoint={600} may collapse to a drawer even when the full page is wider than 600 px.

    The same rule applies to width props: minWidth, maxWidth, and defaultWidth on PageLayout.Details are percentages of the content + details area, not the full page.

    Preserve content state

    Panel content is never unmounted. Component state, scroll positions, and form input values survive collapse and expand cycles without any configuration. To reset state on close, do so explicitly in onCollapsedChange, or conditionally render the slot's children.

    Built-in controls

    Collapse and expand controls are always present in PageLayout.Sidebar and require no configuration. The collapse button appears on hover when the sidebar is expanded. When collapsed, an expand button takes its place.

    Details control bar

    PageLayout.Details.ControlBar is optional. Place it at the top of the details panel to give users a close button and, above the breakpoint, a layout-mode toggle. See Control bar in Usage for placement and customization guidance.

    Disable resizing

    Set resizable={false} to lock a panel to its configured width and hide the drag handle. Use this when the panel width is determined by its content rather than user preference.

    Use with router

    Slot components work correctly inside a router <Outlet />, a <Suspense> boundary, or any other wrapper, including components that conditionally render or lazy-load their children.

    A common pattern is a top-level PageLayout with the header and sidebar defined at the app layout level, and the Content and Details slots provided by individual route components:

    // App layout - defines the persistent layout frame
    const AppLayout = () => (
    <PageLayout>
    <PageLayout.Header>
    <AppHeader>{/* top-level navigation */}</AppHeader>
    </PageLayout.Header>
    <PageLayout.Sidebar>{/* sub-navigation */}</PageLayout.Sidebar>
    {/* Route components render their Content/Details slots here */}
    <Outlet />
    </PageLayout>
    );

    // Route component - only provides the slots it owns
    const DashboardRoute = () => (
    <>
    <PageLayout.Content>
    <DashboardTable />
    </PageLayout.Content>
    <PageLayout.Details>
    <PageLayout.Details.ControlBar />
    <DetailsPanel />
    </PageLayout.Details>
    </>
    );

    When a route lazy-loads its content, wrap it in <Suspense> and render a fallback inside PageLayout.Content to keep the layout stable while loading:

    const LazyDashboard = lazy(() => import('./DashboardRoute'));

    const AppLayout = () => (
    <PageLayout>
    <PageLayout.Header>...</PageLayout.Header>
    <PageLayout.Sidebar>...</PageLayout.Sidebar>
    <Suspense
    fallback={
    <PageLayout.Content>
    <ProgressCircle />
    </PageLayout.Content>
    }
    >
    <Outlet />
    </Suspense>
    </PageLayout>
    );
    Still have questions?
    Find answers in the Dynatrace Community