Side menu · navigation drawer

A complete app sidebar: search, folding groups, nested items, badges and a marker that glides to the current page — it folds to an icon rail on wide screens and becomes a swipeable drawer behind a top bar on phones.

Wide · search (press /) · groups fold · nested items · fold it to an icon rail with the button top-right

Home

Content for home. Pick another item — the marker glides to it.

Phone · ☰ opens the drawer · tap outside, Esc or swipe it left to close

Inbox

Content for inbox. Pick another item — the marker glides to it.

This site's own menu on the left is the same component — narrow the window below 900px to get the top bar and the drawer.

Usage

JavaScript
import { signal, html } from "./index.js";import { SideMenu } from "./components/sidemenu.js"; const page = signal("home");SideMenu({  brand: html`<b>◆ Acme</b>`,  search: true,                                   // "/" focuses it; Enter opens the first match  sections: [    { items: [{ id: "home", label: "Home", icon: homeIcon, href: "/" },              { id: "inbox", label: "Inbox", icon, href: "/inbox", badge: "12" }] },    { title: "Workspace", items: [                // titled groups fold (remembered)      { id: "projects", label: "Projects", icon, children: [{ id: "web", label: "Website", href: "/p/web" }] },      { id: "reports", label: "Reports", icon, href: "/reports", badge: Badge({ label: "New" }) } ] },  ],  active: page,                                   // its group and parent open by themselves  onNavigate: (item, e) => { e.preventDefault(); navigate(item.href); },  footer: userCard, header: workspaceSwitcher, actions: avatar,   // actions: the phone top bar})// wide: sticky, folds to an icon rail · under 900px: a top bar + a drawer (focus trap, Esc, swipe)