Skip to content

Sidebar

wu-sidebar is a navigation column of link sections. Use a <nav aria-label> and aria-current="page" on the current link. Collapsible groups are <details> elements with a <summary> toggle, so they open and close without JavaScript.

Class, attribute or variable Effect
wu-sidebar Root, on <nav>. Surface column with an end border
wu-sidebar-header, wu-sidebar-footer Parts. Rows at the top and the bottom
wu-sidebar-section Part. A heading and its list
wu-sidebar-heading Part. Small muted section heading
wu-sidebar-list Part, on <ul>. Column of links
wu-sidebar-link Part. Row link with hover and inset focus ring
aria-current="page" on a link Current page: tint plus a bar, so color is not the only signal
wu-sidebar-group Part, on <details>. Collapsible group, its list indented
wu-sidebar-toggle Part, on <summary> or a <button aria-expanded>. Row with a chevron
pinned Sticks beside scrolling content and scrolls on its own
collapsed Icon rail: labels hidden visually, shown as a tooltip on hover and focus
wu-sidebar-label Part, a <span> around the link text. Hidden visually in collapsed, still read by screen readers
An <svg> in a link or toggle App icon, sized to the text
animated The chevron turns, groups slide open and the rail width changes smoothly, opt-in
--wu-sidebar--Width Width, 16rem by default
--wu-sidebar--CollapsedWidth Width of the collapsed rail, fits one icon by default
<nav class="wu-sidebar" aria-label="Workspace">
<div class="wu-sidebar-header"><strong>Northwind</strong></div>
<div class="wu-sidebar-section">
<h3 class="wu-sidebar-heading">General</h3>
<ul class="wu-sidebar-list">
<li><a class="wu-sidebar-link" href="#" aria-current="page">Dashboard</a></li>
<li><a class="wu-sidebar-link" href="#">Projects</a></li>
<li><a class="wu-sidebar-link" href="#">Reports</a></li>
</ul>
</div>
<div class="wu-sidebar-section">
<h3 class="wu-sidebar-heading">Account</h3>
<ul class="wu-sidebar-list">
<li><a class="wu-sidebar-link" href="#">Members</a></li>
<li><a class="wu-sidebar-link" href="#">Billing</a></li>
</ul>
</div>
<div class="wu-sidebar-footer"><span class="wu-badge">Team plan</span></div>
</nav>

A group that holds the current page shows its toggle in regular text.

<nav class="wu-sidebar" aria-label="Settings">
<ul class="wu-sidebar-list">
<li><a class="wu-sidebar-link" href="#">Overview</a></li>
<li>
<details class="wu-sidebar-group" open>
<summary class="wu-sidebar-toggle">Settings</summary>
<ul class="wu-sidebar-list">
<li><a class="wu-sidebar-link" href="#" aria-current="page">Profile</a></li>
<li><a class="wu-sidebar-link" href="#">Security</a></li>
</ul>
</details>
</li>
<li>
<details class="wu-sidebar-group">
<summary class="wu-sidebar-toggle">Integrations</summary>
<ul class="wu-sidebar-list">
<li><a class="wu-sidebar-link" href="#">Slack</a></li>
<li><a class="wu-sidebar-link" href="#">Webhooks</a></li>
</ul>
</details>
</li>
</ul>
</nav>
<nav class="wu-sidebar" aria-label="Narrow" style="--wu-sidebar--Width: 12rem">
<ul class="wu-sidebar-list">
<li><a class="wu-sidebar-link" href="#" aria-current="page">Inbox</a></li>
<li><a class="wu-sidebar-link" href="#">Sent</a></li>
</ul>
</nav>

pinned sticks the sidebar to the top beside scrolling content, at most the height of the viewport, and lets it scroll on its own. Put it in a flex row next to the content:

<div class="flex">
<nav class="wu-sidebar pinned" aria-label="Main">...</nav>
<main class="grow">...</main>
</div>

An <svg> placed in a link or a group toggle is sized to the text and takes the text color. Bring your own icons, and put the text in a wu-sidebar-label span so the icon rail below can hide it.

<nav class="wu-sidebar" aria-label="Workspace, icons">
<ul class="wu-sidebar-list">
<li><a class="wu-sidebar-link" href="#" aria-current="page"><svg viewBox="0 0 16 16" aria-hidden="true"><rect x="2" y="2" width="12" height="12" rx="3" fill="none" stroke="currentColor" stroke-width="2"/></svg><span class="wu-sidebar-label">Dashboard</span></a></li>
<li><a class="wu-sidebar-link" href="#"><svg viewBox="0 0 16 16" aria-hidden="true"><rect x="2" y="2" width="12" height="12" rx="3" fill="none" stroke="currentColor" stroke-width="2"/></svg><span class="wu-sidebar-label">Projects</span></a></li>
<li><a class="wu-sidebar-link" href="#"><svg viewBox="0 0 16 16" aria-hidden="true"><rect x="2" y="2" width="12" height="12" rx="3" fill="none" stroke="currentColor" stroke-width="2"/></svg><span class="wu-sidebar-label">Reports</span></a></li>
</ul>
</nav>

collapsed narrows the sidebar to its icons. Labels and headings are hidden visually but stay in the page, so screen readers still announce each link. Hovering or focusing a link shows its label as a tooltip at the inline end. Every link needs an icon and a wu-sidebar-label. The rail does not scroll, so keep its links few.

<nav class="wu-sidebar collapsed" aria-label="Workspace, rail">
<ul class="wu-sidebar-list">
<li><a class="wu-sidebar-link" href="#" aria-current="page"><svg viewBox="0 0 16 16" aria-hidden="true"><rect x="2" y="2" width="12" height="12" rx="3" fill="none" stroke="currentColor" stroke-width="2"/></svg><span class="wu-sidebar-label">Dashboard</span></a></li>
<li><a class="wu-sidebar-link" href="#"><svg viewBox="0 0 16 16" aria-hidden="true"><rect x="2" y="2" width="12" height="12" rx="3" fill="none" stroke="currentColor" stroke-width="2"/></svg><span class="wu-sidebar-label">Projects</span></a></li>
<li><a class="wu-sidebar-link" href="#"><svg viewBox="0 0 16 16" aria-hidden="true"><rect x="2" y="2" width="12" height="12" rx="3" fill="none" stroke="currentColor" stroke-width="2"/></svg><span class="wu-sidebar-label">Reports</span></a></li>
</ul>
</nav>

The kit sets no toggle for you. Toggle the class from a button in your app and mirror the state in aria-expanded:

button.addEventListener('click', () => {
const collapsed = sidebar.classList.toggle('collapsed');
button.setAttribute('aria-expanded', String(!collapsed));
});

The edge, the current bar and the rail tooltips move to the other side.

<nav class="wu-sidebar collapsed" aria-label="סביבת עבודה, סרגל">
<ul class="wu-sidebar-list">
<li><a class="wu-sidebar-link" href="#" aria-current="page"><svg viewBox="0 0 16 16" aria-hidden="true"><rect x="2" y="2" width="12" height="12" rx="3" fill="none" stroke="currentColor" stroke-width="2"/></svg><span class="wu-sidebar-label">לוח בקרה</span></a></li>
<li><a class="wu-sidebar-link" href="#"><svg viewBox="0 0 16 16" aria-hidden="true"><rect x="2" y="2" width="12" height="12" rx="3" fill="none" stroke="currentColor" stroke-width="2"/></svg><span class="wu-sidebar-label">דוחות</span></a></li>
</ul>
</nav>

animated (or wu-animated on an ancestor) turns the chevron and eases the change to and from the icon rail. Groups slide open and closed. Reduced motion turns it off.

<nav class="wu-sidebar animated" aria-label="Animated">
<ul class="wu-sidebar-list">
<li>
<details class="wu-sidebar-group">
<summary class="wu-sidebar-toggle">Reports</summary>
<ul class="wu-sidebar-list">
<li><a class="wu-sidebar-link" href="#">Monthly</a></li>
<li><a class="wu-sidebar-link" href="#">Yearly</a></li>
</ul>
</details>
</li>
</ul>
</nav>

Below md, move the navigation into a drawer docked to the inline start, opened by a menu button. Inside a wu-drawer the sidebar fills the drawer and drops its edge. The drawer is a native modal dialog, so Esc, focus return and the inert page come with no script. The utility classes hide@md and hide flex@md swap the button and the in-page sidebar at md.

<button class="wu-btn hide@md" type="button" commandfor="sidebar-drawer" command="show-modal">Menu</button>
<dialog class="wu-drawer inline-start" id="sidebar-drawer" aria-label="Menu" closedby="any">
<nav class="wu-sidebar" aria-label="Workspace">
<ul class="wu-sidebar-list">
<li><a class="wu-sidebar-link" href="#" aria-current="page">Dashboard</a></li>
<li><a class="wu-sidebar-link" href="#">Projects</a></li>
<li><a class="wu-sidebar-link" href="#">Reports</a></li>
</ul>
<div class="wu-sidebar-footer">
<button class="wu-btn sm" type="button" commandfor="sidebar-drawer" command="close">Close</button>
</div>
</nav>
</dialog>
<nav class="wu-sidebar hide flex@md" aria-label="Workspace">
<ul class="wu-sidebar-list">
<li><a class="wu-sidebar-link" href="#" aria-current="page">Dashboard</a></li>
<li><a class="wu-sidebar-link" href="#">Projects</a></li>
<li><a class="wu-sidebar-link" href="#">Reports</a></li>
</ul>
</nav>
@use "@wovenui/components/sidebar";

The sidebar needs no other component. The narrow screen example also uses the drawer and the button.