Sidebar
Sidebar
Usage
Template macros available
This component ships a sidebar() macro for Jinja and Nunjucks.
Sidebar uses a native <aside> next to your page content. Basecoat owns the fixed positioning, overlay behavior, active states, nested lists, and details submenu styling. Your app still owns the navigation data and current route.
Include CSS
Import Tailwind and one full Basecoat style bundle.
@import "tailwindcss";
@import "basecoat-css/vega.css";Or import only the base CSS, Sidebar component CSS, and one style pack.
@import "tailwindcss";
@import "basecoat-css/base.css";
@import "basecoat-css/components/sidebar.css";
@import "basecoat-css/styles/vega.css";Using CDN or bundler imports? See the Installation page.
Include JavaScript
Copy or serve the full Basecoat JavaScript bundle.
<script src="/assets/js/all.min.js" defer></script>Or copy or serve the Basecoat runtime and Sidebar script.
<script src="/assets/js/basecoat.min.js" defer></script>
<script src="/assets/js/sidebar.min.js" defer></script>Using CDN or bundler imports? See the Installation page.
Add your sidebar HTML
<aside id="sidebar" class="sidebar" data-side="left">
<nav aria-label="Sidebar navigation">
<section class="scrollbar-sm">
<div role="group" aria-labelledby="group-label-content-1">
<h3 id="group-label-content-1">Getting started</h3>
<ul>
<li>
<a href="#">
<svg class="lucide lucide-square-terminal" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m7 11 2-2-2-2" /><path d="M11 13h4" /><rect width="18" height="18" x="3" y="3" rx="2" ry="2" /></svg>
<span>Playground</span>
</a>
</li>
<li>
<a href="#">
<svg class="lucide lucide-bot" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 8V4H8" /><rect width="16" height="12" x="4" y="8" rx="2" /><path d="M2 14h2" /><path d="M20 14h2" /><path d="M15 13v2" /><path d="M9 13v2" /></svg>
<span>Models</span>
</a>
</li>
<li>
<details id="submenu-content-1-3">
<summary aria-controls="submenu-content-1-3-content"><svg class="lucide lucide-settings" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915" /><circle cx="12" cy="12" r="3" /></svg>
<span>Settings</span>
</summary>
<ul id="submenu-content-1-3-content">
<li><a href="#"><span>General</span></a></li>
<li><a href="#"><span>Team</span></a></li>
<li><a href="#"><span>Billing</span></a></li>
<li><a href="#"><span>Limits</span></a></li>
</ul>
</details>
</li>
</ul>
</div>
</section>
</nav>
</aside>
<main>
<button type="button" onclick="document.getElementById('sidebar')?.toggle()">Toggle sidebar</button>
<h1>Content</h1>
</main> RTL
Set dir="rtl" on the sidebar or a parent element. Logical spacing, nested borders, and item content follow document direction. data-side is physical: left and right refer to viewport sides.
Differences with shadcn/ui
Basecoat intentionally supports the stable HTML sidebar surface: fixed left/right sidebars, mobile overlay behavior, grouped navigation, active states, and native details submenus. It does not expose shadcn/ui’s React provider, rail, inset/floating variants, icon-only collapse mode, menu actions, menu badges, or menu skeleton API.
HTML structure
Basecoat maps shadcn/ui’s sidebar composition to regular navigation HTML: an <aside> root, one <nav>, optional header/footer regions, grouped lists, item controls, and native <details> for nested menus.
<aside class=“sidebar”>Sidebar root. Supports
id,data-side=“left|right”,data-initial-open=“false”,data-initial-mobile-open=“true”, anddata-breakpoint. JavaScript managesaria-hidden,inert, and the internaldata-sidebar-initializedflag.<nav aria-label=”…”>Navigation landmark inside the sidebar.
<header>- Optional header for branding, workspace controls, user controls, or persistent actions.
<section>Scrollable content region between the optional header and footer.
<div role=“group” aria-labelledby=”…”>- Named navigation group. Use a heading element as the group label.
<ul>+<li>Menu and menu item structure. Top-level lists and nested submenu lists receive different spacing and borders.
<a>/<button>- Menu item control. Use links for navigation and buttons for actions. Supports
data-variant=“default|outline”,data-size=“default|sm|lg”,data-active=“true”,disabledon buttons, andaria-disabled=“true”on custom-disabled controls. For links, prefer<a aria-current=“page”>for the current page. Adddata-keep-mobile-sidebar-openon a clicked link, button, or ancestor when that control should not close the mobile sidebar. <details>/<summary>- Native disclosure for collapsible submenus. Put the nested
<ul>directly after<summary>. The<summary>supports the same active, variant, and size attributes as menu item controls. Addidandaria-controlswhen the relationship is not obvious from nearby markup. <hr role=“separator”>- Optional separator between groups or menu sections.
<footer>- Optional footer for account controls, status, or persistent actions.
<main>- Sibling content wrapper. The desktop margin applies to the sibling immediately after the sidebar.
Set --sidebar-width and --sidebar-mobile-width on :root or the sidebar root to override the default 16rem desktop width and 18rem mobile width.