Sidebar
The app-shell sidebar composes NavigationMenu inside a sticky column — the docs site you're reading uses exactly this recipe.
Recipe
import { NavigationMenu } from '@elirobinson/react/components/organisms/NavigationMenu';
export function AppSidebar({ currentPath }: { currentPath: string }) {
return (
<div className="shell">
<aside className="shell__sidebar">
<NavigationMenu
aria-label="Application"
currentPath={currentPath}
items={[
{ label: 'Dashboard', href: '/dashboard' },
{
label: 'Guides',
href: '/guides',
items: [
{ label: 'Drafts', href: '/guides/drafts' },
{ label: 'Published', href: '/guides/published' },
],
},
{ label: 'Orders', href: '/orders' },
{ label: 'Settings', href: '/settings' },
]}
/>
</aside>
<main className="shell__main">{/* page content */}</main>
</div>
);
}.shell {
display: grid;
grid-template-columns: 260px minmax(0, 1fr);
gap: var(--space-10);
max-width: var(--container-2xl);
margin: 0 auto;
padding: var(--space-8) var(--gutter);
}
.shell__sidebar {
position: sticky;
top: calc(64px + var(--space-6)); /* header height + breathing room */
align-self: start;
max-height: calc(100vh - 64px - var(--space-8));
overflow-y: auto;
}
@media (max-width: 960px) {
.shell {
grid-template-columns: minmax(0, 1fr);
}
.shell__sidebar {
display: none; /* move nav into a Sheet-triggered menu */
}
}Rules
- 260px wide, sticky below the header, scrolling independently when tall.
NavigationMenumarks the current page witharia-current— pass the live pathname.- Nav items are primary controls: keep their 44px hit height when restyling.
- Under 960px, don't shrink the sidebar — replace it with a Sheet menu from the top bar.
- Section labels (if you add them above groups) are mono uppercase eyebrows, not
headings. Add them as items with no
href— a header carrying its first child's href renders as the current page whenever that child is open.