Skip to content

Sidebar

Sticky section navigation with native collapsible groups, active links, and a footer.

Block · navigation

Terminal window
npx shadcn@latest add https://ndigo.dev/r/sidebar.json

To use the shorter @ndigo/sidebar form, configure the namespace in components.json.

Source Target Type
registry/blocks/sidebar/sidebar.html @components/sidebar/sidebar.html registry:block
registry/blocks/sidebar/sidebar.css @components/sidebar/sidebar.css registry:file

See this component rendered live on the live examples page.

Registry: Ndigo theme.

The sidebar is markup plus CSS. <details> gives each group disclosure behaviour with no JavaScript, and the panel sticks beside the content on wide screens.

<aside class="nd-sidebar" aria-label="Section navigation">
<div class="nd-sidebar__header">
<span class="nd-sidebar__brand">Workspace</span>
<span class="nd-sidebar__version">v0.0.1</span>
</div>
<nav class="nd-sidebar__nav">
<details class="nd-sidebar__group" open>
<summary class="nd-sidebar__group-label">Getting started</summary>
<ul class="nd-sidebar__list">
<li><a class="nd-sidebar__link" href="#overview" aria-current="page">Overview</a></li>
<li><a class="nd-sidebar__link" href="#install">Installation</a></li>
</ul>
</details>
</nav>
<div class="nd-sidebar__footer">
<a class="nd-sidebar__link" href="#settings">Settings</a>
</div>
</aside>

Put the panel in a layout grid with the content; align-self: start keeps the sticky panel from stretching.

Class Purpose
.nd-sidebar__header Brand and version
.nd-sidebar__nav Group container
.nd-sidebar__group Native <details> group
.nd-sidebar__group-label <summary> with a rotating chevron
.nd-sidebar__list Link list
.nd-sidebar__link Link; aria-current="page" marks active
.nd-sidebar__footer Settings and secondary links

Below 48rem the panel stops being sticky and stacks above the content at full width. For an off-canvas mobile panel, host the same <nav> partial inside nd-drawer (placement="start") and show the drawer trigger only below the breakpoint; keep one source for the nav so the two surfaces cannot drift.

  • Use an <aside> with a distinct aria-label; it is a complementary landmark.
  • <details>/<summary> are keyboard operable natively; do not replace them with click handlers on a <div>.
  • Mark exactly one current link per navigation with aria-current="page".
  • The chevron is CSS-generated and presentational; the group label carries the name.

Import sidebar.css after the tokens. The panel uses the surface and border tokens; hover, focus, and the active link use the accent-soft token. Reduced motion removes the chevron transition.