Prototype Library

Sidebar Nav

Collapsible side navigation with grouped sections, accordion children, badges, and a collapse-to-rail toggle. A Lit web component, because the collapse and accordion states are real runtime behavior.

Inherited wc import '@esa/ecology/esa-sidebar-nav';

Preview

Use the chevrons button at the top to collapse to an icon rail; click Reports to expand its children.

<esa-sidebar-nav id="demo"></esa-sidebar-nav>

<script>
  const el = document.getElementById('demo');
  el.items = [
    { label: 'Dashboard', href: '/dashboard', active: true, group: 'Main' },
    { label: 'Projects', href: '/projects', badge: 12, group: 'Main' },
    { label: 'Reports', group: 'Main', children: [
      { label: 'Monthly', href: '/reports/monthly' },
      { label: 'Quarterly', href: '/reports/quarterly' },
    ] },
    { label: 'Team', href: '/team', group: 'Admin' },
    { label: 'Billing', href: '/billing', group: 'Admin', disabled: true },
    { label: 'Settings', href: '/settings', group: 'Admin' },
  ];
</script>

States

Non-collapsible — set collapsible="false" to hide the toggle and lock the sidebar at full width.

<esa-sidebar-nav id="demo2" collapsible="false"></esa-sidebar-nav>

API

PropTypeDefaultDescription
items EsaSidebarNavItem[] [] Nav items (property, set via JS). Each is { label; href?; icon?; badge?; children?; disabled?; group?; active? }. Consecutive items sharing a group render under a group heading.
label string 'Sidebar' Accessible name for the navigation landmark. Do not include the word "navigation" — the role is announced with it. Give two rails on one page distinct labels so the landmark list can tell them apart.
collapsed boolean false Collapses to an icon rail. Reflected as an attribute.
collapsible boolean true Shows the collapse toggle. Set false to lock the sidebar open. On by default. Write `="false"` to turn it off — unusually for a boolean attribute, this one reads the value.
drawer boolean false Drawer mode: the rail becomes a slide-out overlay instead of an in-flow column, for narrow viewports. esa-app-shell sets this from a matchMedia. The <nav> landmark stays on the page in both modes — only its contents hide — and the toggle stays inside the landmark, so navigating to it while shut lands on the control that opens it.
drawer-open boolean false Whether the drawer is shown. Only meaningful with drawer. While open, the drawer emits drawerchange so the host can make the rest of the page inert. Property: `drawerOpen`.

Events

EventTypeDefaultDescription
collapsedchange CustomEvent — Fired when the collapse toggle is clicked. detail: { collapsed: boolean }. Bubbles and composed.
Binding these events from Angular

Every one of these is a CustomEvent, so the payload is on $event.detail — $event.target.value reads empty, with no error. The names are lowercase and Angular passes them to addEventListener verbatim, so camel-casing one means it never fires.

  • (collapsedchange)="onCollapsedchange($event.detail)"
  • (drawerchange)="onDrawerchange($event.detail)"

items is an array property — set it in JS, not as an attribute. Each EsaSidebarNavItem.icon is a raw inline SVG string.

Slots

PropTypeDefaultDescription
header slot — Logo / brand area pinned above the nav list.

Accessibility

  • Renders a <nav aria-label="Sidebar navigation"> over a semantic list.
  • Active leaf links carry aria-current="page"; parent accordions expose aria-expanded.
  • The collapse toggle's aria-label flips between Collapse sidebar / Expand sidebar.
  • Disabled items are removed from the tab order (tabindex="-1", pointer-events: none).