# SidebarLayout

> Page-scale chrome - optional header row on top of a sidebar + main grid. The aside column collapses at the md breakpoint (≤ 768 px) so mobile screens stay single-column.

- Category: layout
- Status: stable (since 0.3.0)
- A11y pattern: https://www.w3.org/WAI/ARIA/apg/patterns/landmarks/
- Tokens: --background-primary, --foreground-primary
- Playground: https://design.freecodecamp.org/playground#sidebar-layout
- npm dependencies: `react@>=18 <20`
- Registry dependencies: [theme](https://design.freecodecamp.org/registry/theme.md)
- Files:
  - `SidebarLayout.tsx` → `src/ui/sidebar-layout/SidebarLayout.tsx` (raw: https://design.freecodecamp.org/registry/sidebar-layout/SidebarLayout.tsx)
  - `sidebar-layout.css` → `src/ui/sidebar-layout/sidebar-layout.css` (raw: https://design.freecodecamp.org/registry/sidebar-layout/sidebar-layout.css)

## Install (copy source)

1. Ensure the theme is installed once per project - tokens.css + base.css imported globally, fonts available. See https://design.freecodecamp.org/registry/theme.md and https://design.freecodecamp.org/registry/starter.md.
2. Copy the files below into `src/ui/sidebar-layout/` (adjust to your project layout) and import the CSS once from your global stylesheet, e.g. `@import './ui/sidebar-layout/sidebar-layout.css';`.
3. Colors, spacing and type come from tokens - tailor the component by editing the copied source; recolour by editing tokens.css, not the component CSS.

## Usage

SidebarLayout is the full-page shell for app screens with a persistent
side rail. Drop a Navbar into `header`, a Sidebar into `sidebar`, and
your route content as children - the grid math and responsive
collapse are already wired.

## Accessibility

Semantic landmarks come from the slot contents - Navbar brings
`role="banner"`, Sidebar brings `role="navigation"`, and the main
column is a native `<main>`. The layout itself ships no landmarks so
consumers can swap Navbar/Sidebar for custom chrome without
duplication.

## Example

```tsx
import { SidebarLayout } from './ui/sidebar-layout/SidebarLayout';
import { Sidebar } from './ui/sidebar/Sidebar';
import { Navbar } from './ui/navbar/Navbar';

<SidebarLayout
  header={<Navbar … />}
  aside={<Sidebar … />}
>
  {children}
</SidebarLayout>
```

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `header` | `ReactNode` | no | - |  |
| `sidebar` | `ReactNode` | no | - |  |

## Source: SidebarLayout.tsx

```tsx
import React, { forwardRef } from 'react';

export interface SidebarLayoutProps extends React.HTMLAttributes<HTMLDivElement> {
  header?: React.ReactNode;
  sidebar?: React.ReactNode;
}

export const SidebarLayout = forwardRef<HTMLDivElement, SidebarLayoutProps>(
  ({ header, sidebar, className = '', children, ...rest }, ref) => {
    const classes = ['sidebar-layout', className].filter(Boolean).join(' ');
    return (
      <div ref={ref} className={classes} {...rest}>
        {header !== undefined && (
          <div className='sidebar-layout__header'>{header}</div>
        )}
        <div className='sidebar-layout__body'>
          {sidebar !== undefined && (
            <div className='sidebar-layout__aside'>{sidebar}</div>
          )}
          <main className='sidebar-layout__main'>{children}</main>
        </div>
      </div>
    );
  }
);
SidebarLayout.displayName = 'SidebarLayout';
```

## Source: sidebar-layout.css

```css
.sidebar-layout {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  background: var(--background-primary);
  color: var(--foreground-primary);
}
.sidebar-layout__header {
  flex: 0 0 auto;
}
.sidebar-layout__body {
  display: grid;
  grid-template-columns: 220px 1fr;
  flex: 1 1 auto;
  min-height: 0;
}
.sidebar-layout__aside {
  min-height: 0;
  overflow-y: auto;
}
.sidebar-layout__main {
  padding: 24px;
  min-width: 0;
  overflow-x: hidden;
}
@media (max-width: 768px) {
  .sidebar-layout__body {
    grid-template-columns: 1fr;
  }
  .sidebar-layout__aside {
    display: none;
  }
}
```

## HTML / vanilla variant

```html
<div class="sidebar-layout">
  <header class="sidebar-layout__header">…</header>
  <div class="sidebar-layout__body">
    <aside class="sidebar-layout__aside">…</aside>
    <main class="sidebar-layout__main">…</main>
  </div>
</div>
```

Interactive behaviours for plain HTML come from the vanilla runtime (data-uikit-* attributes): https://design.freecodecamp.org/registry/vanilla.md - or download https://design.freecodecamp.org/cdn/uikit.global.js once and self-host it (do not hotlink).

## For coding agents

This library is distributed as copyable source, not an npm package. Start at https://design.freecodecamp.org/registry/starter.md, discover components via https://design.freecodecamp.org/llms.txt, and copy files into the consuming project. Keep token names intact; recolour by editing the copied tokens.css.
