A sidebar navigation component for application dashboards and admin panels. Supports collapsible accordion groups, an icon-strip mode with hover-expand and CSS tooltip fallback for collapsed labels, a mobile slide-in drawer with blurred backdrop, optional
localStorage
persistence of the collapsed and group state, and a full programmatic API. The same toggle button works on both desktop (collapse/expand) and mobile (open/close drawer).
Real-World Example
The demo below shows a complete admin shell. Click the sidebar toggle button to collapse to icon-strip mode — hover over it to expand temporarily. On mobile the sidebar slides in as a full-screen overlay.
A sidenav is built from four vertical sections. The
wf-sidenav-header
holds the brand and the collapse toggle button. The optional
wf-sidenav-user
block sits immediately below it. The scrollable
wf-sidenav-body
contains all navigation items, labels, groups, and dividers. The
wf-sidenav-footer
is pinned to the bottom and is used for utility links like Settings and Help. All sections except the header and body are optional.
Wrap a parent trigger button and a
div.wf-sidenav-sub
in a
div.wf-sidenav-group[data-wf-sidenav-group]
. The trigger button must carry the
wf-sidenav-item--parent
modifier class. The script toggles the
data-wf-open
attribute on the group element and uses a
max-height
transition to reveal the sub-list. By default, groups behave as an accordion — opening one closes the others. See
Multi-Open
to change this.
Add
data-wf-open
to a group in the HTML to start it open. A group whose sub-list contains an item with
wf-active
or
aria-current="page"
is also automatically opened by the script on init, and the parent trigger gains
wf-active
to highlight the active section.
Add a
span.wf-sidenav-badge
inside any item to show a notification count. The badge is positioned after
wf-sidenav-text
via
margin-inline-start: auto
and hidden automatically in collapsed icon-strip mode. Use
hr.wf-sidenav-divider
between sections of the body or footer to add a subtle horizontal rule.
HTML
<!-- Item with badge -->
<a class="wf-sidenav-item" href="/inbox" title="Inbox">
<i class="icon mail wf-sidenav-icon" aria-hidden="true"></i>
<span class="wf-sidenav-text">Inbox</span>
<span class="wf-sidenav-badge">3</span>
</a>
<!-- Divider between nav sections -->
<hr class="wf-sidenav-divider">
Collapsed Strip
On desktop, clicking the collapse toggle shrinks the sidebar to a 64 px icon-strip by adding
data-wf-collapsed
to the root element. All text labels, chevrons, and badges are hidden; only icons remain. Hovering the strip temporarily expands it back to full width so the user can read labels and interact with groups — the expansion uses pure CSS (
:hover
+
@starting-style
for a smooth opacity fade-in).
Add a
title
attribute to every
wf-sidenav-item
to enable the built-in CSS tooltip that appears next to the icon when the strip is collapsed and not hovered. Start the sidebar already collapsed by adding
data-wf-collapsed
directly in the HTML.
HTML
<!-- Start in collapsed state -->
<aside class="wf-sidenav" data-wf-sidenav data-wf-collapsed>
...
<!-- title enables the CSS tooltip in stripped mode -->
<a class="wf-sidenav-item" href="/analytics" title="Analytics">
<i class="icon chart bar wf-sidenav-icon"></i>
<span class="wf-sidenav-text">Analytics</span>
</a>
...
</aside>
Mobile Drawer
Below the breakpoint (default 768 px) the sidebar switches to
position: fixed
and is hidden off-screen. Any element carrying
data-wf-sidenav-toggle
— whether inside or outside the sidebar — will open or close it. Use an external toggle in your topbar to provide a hamburger button that is visible when the sidebar is hidden. The script appends a
wf-sidenav-backdrop
to
<body>
; clicking it closes the drawer.
HTML
<!-- External toggle (e.g. inside a topbar) -->
<button data-wf-sidenav-toggle aria-label="Open menu">
<i class="icon menu" aria-hidden="true"></i>
</button>
<!-- Sidebar -->
<aside class="wf-sidenav" data-wf-sidenav>
<div class="wf-sidenav-header">
<a class="wf-sidenav-brand" href="/">...</a>
<!-- Internal close button inside the sidebar header -->
<button class="wf-sidenav-collapse-btn" data-wf-sidenav-toggle aria-label="Close sidebar">
<i class="icon chevrons left"></i>
</button>
</div>
...
</aside>
<!-- Backdrop is injected by the script; no markup needed -->
Multi-Open
By default, the sidenav is in accordion mode — opening a group closes all others. Add
data-wf-multi-open
to the root element to allow any number of groups to be open at the same time.
Add
data-wf-persist-collapsed
to remember the collapsed/expanded state in
localStorage
across page loads. Add
data-wf-persist-groups
to remember which groups the user has opened. Group state is stored by index position inside the sidebar so it is best suited to a sidebar whose item order does not change between pages.
HTML
<!-- Persist collapsed state only -->
<aside class="wf-sidenav" data-wf-sidenav data-wf-persist-collapsed>...</aside>
<!-- Persist both collapsed state and open groups -->
<aside class="wf-sidenav" data-wf-sidenav data-wf-persist-collapsed data-wf-persist-groups>...</aside>
Data Attributes
Attribute
Element
Description
data-wf-sidenav
.wf-sidenav
Initializes the component on this element.
data-wf-sidenav-toggle
Any button
Marks a button as the collapse/hamburger toggle. Can appear inside or outside the sidebar. Multiple buttons are supported.
data-wf-sidenav-group
.wf-sidenav-group
Marks an element as a collapsible group container.
data-wf-open
[data-wf-sidenav-group]
Opens the group on init. Also set/removed by the script at runtime.
data-wf-collapsed
.wf-sidenav
Starts the sidebar in icon-strip mode. Also set/removed by the script at runtime.
data-wf-multi-open
.wf-sidenav
Allows multiple groups to be open simultaneously (disables accordion behavior).
data-wf-persist-collapsed
.wf-sidenav
Saves the collapsed/expanded state to localStorage across page loads.
data-wf-persist-groups
.wf-sidenav
Saves the open groups (by index) to localStorage across page loads.
CSS Properties
All tokens are scoped to
.wf-sidenav
so multiple sidebars on the same page can have independent themes.
Property
Default
Description
--wf-snav-width
260px
Full expanded width of the sidebar.
--wf-snav-width-col
64px
Width of the collapsed icon-strip.
--wf-snav-bg
var(--wf-surface)
Background color of the sidebar.
--wf-snav-border
var(--wf-border)
color of the inline-end border and section dividers.
--wf-snav-text
var(--wf-text)
Default text color for items, brand, and username.
--wf-snav-muted
var(--wf-text-muted)
Muted text color for labels, role, chevrons, and sub-items.
--wf-snav-accent
var(--wf-primary)
Accent color used for the logo box, avatar, badge, and active states.