LayoutStable

Side Nav

Sourcecomponents/SideNav.astro

The rail

The sticky dashboard sidebar — a logo header, grouped rows (each an optional label and a set of Side Nav Items), a Divider, and a User Chip at the foot. It sticks to the viewport and scrolls internally when the list is tall.

Switch viewport, or scroll the preview — the rail stays put while the content scrolls.

Sticky side navigation

Built from

  • Side Nav Item — each row: a stroke icon, a label, and the active state.
  • Divider — the hairline above the foot.
  • User Chip — the signed-in identity, itself built from Avatar.

Behaviour

  • Sticky — position: sticky; top: 0 at 100svh; the row list scrolls inside while the logo and user chip stay pinned.
  • Icons are passed inline per item (an SVG string, fill="none" stroke="currentColor") so each takes its row's colour — including violet on the active row.
  • ≤900px — the rail unpins and spans full width with a bottom border, for a top-of-page strip.

Props

PropTypeDefaultNotes
groups NavGroup[] — The sections. Each { label?, items: { label, href, icon?, active? }[] }. Required.
user User — Foot identity — { name, role?, avatarSrc?, initials?, href? }. Omit to hide.
logo string '/img/logo-dark.svg' The header logo (dark, for the cream rail).
logoHref string '/' Where the logo links.
logoAlt string 'Alchemy Zurich' Logo alt text + brand aria-label.

Usage

Give it groups and a user. Mark the current page with active: true on its item. Place it as the first child of a flex shell beside your content.

---
import SideNav from '../components/SideNav.astro';

const eye = '<svg viewBox="0 0 20 20" fill="none">…</svg>';   // inline stroke icon
const groups = [
  { label: 'Aktive Projekte', items: [{ label: 'Essential Brand Projekt', href: '/p/essential', icon: eye }] },
  { label: 'Generell', items: [
    { label: 'Website', href: '/website', icon: globe },
    { label: 'Formulare', href: '/forms', icon: doc },
  ] },
  { label: 'Hilfe', items: [
    { label: 'Chat', href: '/chat', icon: chat },
    { label: 'Alchemy Shop', href: '/shop', icon: shop, active: true },
  ] },
];
const user = { name: 'Alex Morgan', role: 'Designer', initials: 'AZ' };
---
<SideNav {groups} {user} />

Rules

Do

Group rows under short section labels — one word or two.

Mark exactly one item active — the page you're on.

Don't

Mix this app rail with the site top Navigation — one or the other.

Letter-space the section labels — labels stay at 0.