stable css 1.2.2 · js 1.2.0

Sidebar

The app-shell side navigation: sticky, collapsible, with expandable submenus and a mobile drawer mode. It sits as the first child of a ng-layout. Link ng_sidebar.js. This very page uses one.

Inside the real layout the sidebar is sticky and viewport-tall (here the demos are framed). Links are ng-sidebar-link; expandable entries pair a ng-sidebar-trigger with a sibling ng-sidebar-submenu. Below 992px it becomes a drawer automatically.

Full structure

Header (brand), scrollable body with ng-sidebar-title groups, dividers and badges, and a pinned footer.

Page content

The sidebar sits beside the content because ng-layout is a flex row.

sidebar.html
<div class="ng-layout nxi-shell">
    <aside class="ng-sidebar" id="sb-full">
        <div class="ng-sidebar-header">
            <a href="#" class="fw-700"><i class="ph-fill ph-cube text-purple fs-2xl mr-10"></i>Acme Corp</a>
        </div>
        <nav class="ng-sidebar-body">
            <div class="ng-sidebar-title"><span class="fs-xs text-mute text-upper fw-700">Workspace</span></div>
            <ul class="ng-sidebar-nav">
                <li><a href="#" class="ng-sidebar-link is-active" aria-current="page"><i class="ph ph-house"></i><span>Dashboard</span></a></li>
                <li><a href="#" class="ng-sidebar-link"><i class="ph ph-users"></i><span>Customers</span></a></li>
                <li><a href="#" class="ng-sidebar-link"><i class="ph ph-folder-open"></i><span>Projects</span><span class="ng-badge ng-badge-primary-soft pill ml-auto">12</span></a></li>
            </ul>
            <div class="ng-sidebar-divider"></div>
            <div class="ng-sidebar-title"><span class="fs-xs text-mute text-upper fw-700">System</span></div>
            <ul class="ng-sidebar-nav">
                <li><a href="#" class="ng-sidebar-link"><i class="ph ph-gear"></i><span>Settings</span></a></li>
            </ul>
        </nav>
        <div class="ng-sidebar-footer">
            <a href="#" class="ng-sidebar-link"><span class="ng-avatar sm circle bg-purple">CP</span><span>Claudio P.</span></a>
        </div>
    </aside>
    <main class="pxy-24">
        <div class="ng-card">
            <div class="ng-card-body">
                <h3 class="fs-lg fw-700 mb-8">Page content</h3>
                <p class="text-mute">The sidebar sits beside the content because <code>ng-layout</code> is a flex row.</p>
            </div>
        </div>
    </main>
</div>

Submenus (nested)

Click Settings, then Security: submenus nest and animate; indentation is automatic.

Page content

The sidebar sits beside the content because ng-layout is a flex row.

sidebar.html
<div class="ng-layout nxi-shell">
    <aside class="ng-sidebar" id="sb-sub">
        <a href="#" class="ng-sidebar-link is-active"><i class="ph ph-house"></i><span>Dashboard</span></a>
        <button type="button" class="ng-sidebar-trigger">
            <i class="ph ph-gear"></i><span>Settings</span><i class="ph ph-caret-down ml-auto"></i>
        </button>
        <div class="ng-sidebar-submenu">
            <a href="#" class="ng-sidebar-link"><span>Profile</span></a>
            <button type="button" class="ng-sidebar-trigger">
                <span>Security</span><i class="ph ph-caret-down ml-auto"></i>
            </button>
            <div class="ng-sidebar-submenu">
                <a href="#" class="ng-sidebar-link"><span>Password</span></a>
                <a href="#" class="ng-sidebar-link"><span>Two-factor</span></a>
            </div>
            <a href="#" class="ng-sidebar-link"><span>Billing</span></a>
        </div>
        <a href="#" class="ng-sidebar-link"><i class="ph ph-chart-bar"></i><span>Reports</span></a>
    </aside>
    <main class="pxy-24">
        <div class="ng-card">
            <div class="ng-card-body">
                <h3 class="fs-lg fw-700 mb-8">Page content</h3>
                <p class="text-mute">The sidebar sits beside the content because <code>ng-layout</code> is a flex row.</p>
            </div>
        </div>
    </main>
</div>

Compact toggle

A control with data-ng-sidebar-toggle="id" collapses the sidebar (ng-sidebar-compact on the layout). Note ng-sidebar-always on the layout: without it the toggle is hidden above 992px.

Page content

The sidebar sits beside the content because ng-layout is a flex row.

sidebar.html
<button type="button" class="ng-btn ng-btn-primary-outline mb-16" data-ng-sidebar-toggle="sb-toggle">
    <i class="ph ph-arrows-in-line-horizontal"></i>&nbsp; Toggle compact
</button>

<div class="ng-layout ng-sidebar-always nxi-shell">
    <aside class="ng-sidebar" id="sb-toggle">
        <a href="#" class="ng-sidebar-link is-active"><i class="ph ph-house"></i><span>Dashboard</span></a>
        <a href="#" class="ng-sidebar-link"><i class="ph ph-users"></i><span>Customers</span></a>
        <a href="#" class="ng-sidebar-link"><i class="ph ph-gear"></i><span>Settings</span></a>
    </aside>
    <main class="pxy-24">
        <div class="ng-card">
            <div class="ng-card-body">
                <h3 class="fs-lg fw-700 mb-8">Page content</h3>
                <p class="text-mute">The sidebar sits beside the content because <code>ng-layout</code> is a flex row.</p>
            </div>
        </div>
    </main>
</div>

Modes & controls

The active link (ng-sidebar-link.is-active) shows a full-height brand accent bar on the left; override its colour per sidebar with --ng-sidebar-active-accent.

Inline (default)Sticky column in the layout; the toggle switches ng-sidebar-compact.
Drawer (mobile)Below 992px the sidebar is position: fixed; the toggle opens it (ng-sidebar-open on the layout) over the page with the layout overlay.
is-compact / is-textWidth presets on the sidebar (icon-only / narrow text).
Controlsdata-ng-sidebar-toggle / -open / -close = "id"; ARIA expanded is kept in sync.
Right sideng-sidebar-right on the layout flips the sidebar to the other edge.

Accessibility drawer mode

When the sidebar acts as a drawer (mobile / fixed overlay), it behaves as a modal dialog for keyboard and screen-reader users:

EscCloses the open drawer.
Focus trapWhile the drawer is open, focus stays inside it (Tab cycles within).
Focus returnOn close, focus returns to the control that opened the drawer.

This applies only in drawer mode — the static desktop / compact sidebar keeps normal in-page focus flow.

Anatomy

ng-sidebar ng-sidebar-header ng-sidebar-body ng-sidebar-footer ng-sidebar-title ng-sidebar-nav ng-sidebar-link ng-sidebar-trigger ng-sidebar-submenu ng-sidebar-divider

States & layout classes

is-active is-open is-compact is-text is-submenu-active ng-sidebar-open ng-sidebar-compact ng-sidebar-always ng-sidebar-right

Controls

data-ng-sidebar-toggle="id" data-ng-sidebar-open="id" data-ng-sidebar-close="id"

Reference

Generated from the component source (_ng_sidebar.scss · ng_sidebar.js).

Component info

Namesidebar
Typecss+js
Versioncss 1.2.2 · js 1.2.0
Statusstable
CSS/assets/css/components/_ng_sidebar.scss
JS/assets/js/ng_sidebar.js
Dependenciesoverlay

Classes

.ng-layout .ng-sidebar .ng-sidebar-always .ng-sidebar-compact .ng-sidebar-open .ng-sidebar-submenu

Tokens

--ng-sidebar-active --ng-sidebar-active-accent --ng-sidebar-bg --ng-sidebar-border --ng-sidebar-color --ng-sidebar-divider --ng-sidebar-gap --ng-sidebar-hover --ng-sidebar-indent-2 --ng-sidebar-indent-3 --ng-sidebar-item-h --ng-sidebar-muted --ng-sidebar-pad --ng-sidebar-submenu-bg --ng-sidebar-submenu-border --ng-sidebar-submenu-border-radius --ng-sidebar-submenu-margin-top --ng-sidebar-width --ng-sidebar-width-compact --ng-sidebar-width-text