Live: try it with the mouse and the keyboard (Tab, arrows, Escape).

Sidebar navigation UI component for websites and web apps, shown in Wardline, a fictional developer product. Shows a vertical app sidebar with a current page, a count badge, a collapsible Reports group, a locked item and a collapse-to-icons button, plus every link state (default, hover, focus-visible, current, disabled). Minimal style: cool neutrals, Inter, 8px corners and soft shadows. Comes with copyable HTML, CSS and a few lines of plain JavaScript (keyboard support and ARIA per the WAI-ARIA Authoring Practices), a live demo, and a DESIGN.md with light and dark colour tokens.
#f9fcff · surface #ffffff · text #192028 · muted #5b6470 · primary #2168ba · accent #736cd8#10151a · surface #20262e · text #eff1f4 · muted #aab2bc · primary #70aefd · accent #b9bbffPaste the HTML where the component goes, the CSS into your stylesheet and the script before </body>. The tokens block holds the light and dark colours; swap in your own.
<div class="mgd-side-demo">
<nav class="mgd-side" id="side" aria-label="Main">
<div class="mgd-side__top"><span class="mgd-side__brand"><b class="mgd-side__mark" aria-hidden="true"></b><span>Wardline</span></span>
<button class="mgd-side__collapse" type="button" aria-expanded="true" aria-controls="side" aria-label="Collapse sidebar"><svg class="i" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M15 5l-7 7 7 7"/></svg></button></div>
<ul>
<li><a class="mgd-side__link" href="#overview" aria-current="page"><svg class="i" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 11l9-7 9 7v9a1 1 0 0 1-1 1h-5v-6H9v6H4a1 1 0 0 1-1-1z"/></svg><span class="mgd-side__label">Overview</span></a></li>
<li><a class="mgd-side__link" href="#alerts"><svg class="i" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 16V11a6 6 0 0 1 12 0v5l1.5 2h-15zM10 20.5a2 2 0 0 0 4 0"/></svg><span class="mgd-side__label">Alerts</span><span class="mgd-side__count"><span class="mgd-sr">, </span>3<span class="mgd-sr"> new</span></span></a></li>
<li><a class="mgd-side__link" href="#assets"><svg class="i" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 3l8 3v6c0 4.5-3.4 8-8 9-4.6-1-8-4.5-8-9V6z"/></svg><span class="mgd-side__label">Assets</span></a></li>
<li><button class="mgd-side__link" type="button" aria-expanded="true" aria-controls="side-reports"><svg class="i" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 20V10M10 20V4M16 20v-7M22 20H2"/></svg><span class="mgd-side__label">Reports</span><span class="mgd-side__chev"><svg class="i" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 9l7 7 7-7"/></svg></span></button>
<ul class="mgd-side__sub" id="side-reports">
<li><a class="mgd-side__link" href="#weekly"><span class="mgd-side__label">Weekly summary</span></a></li>
<li><a class="mgd-side__link" href="#compliance"><span class="mgd-side__label">Compliance</span></a></li>
<li><a class="mgd-side__link" href="#exports"><span class="mgd-side__label">Exports</span></a></li>
</ul></li>
<li><a class="mgd-side__link" role="link" aria-disabled="true"><svg class="i" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="5" y="11" width="14" height="10" rx="2"/><path d="M8 11V8a4 4 0 0 1 8 0v3"/></svg><span class="mgd-side__label">Audit log (Enterprise)</span></a></li>
</ul>
<ul class="mgd-side__foot"><li><a class="mgd-side__link" href="#settings"><svg class="i" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="3"/><path d="M12 2v3M12 19v3M2 12h3M19 12h3M4.9 4.9l2.1 2.1M17 17l2.1 2.1M4.9 19.1L7 17M17 7l2.1-2.1"/></svg><span class="mgd-side__label">Settings</span></a></li></ul>
</nav>
<div class="mgd-side-main"><h3>Overview</h3><p>4 open findings across 128 cloud assets. Last scan 6 minutes ago.</p></div>
</div>/* Tokens (light + dark) */
:root{--bg:#f9fcff;--surface:#ffffff;--border:#d3dbe6;--text:#192028;--muted:#5b6470;--primary:#2168ba;--on-primary:#ffffff;--accent:#736cd8;--font-h:"Inter",Georgia,serif;--font-b:"Inter",system-ui,sans-serif;--hw:600;
--c-bw:1px;--c-line:var(--border);--c-r:8px;--c-pill:8px;--c-sh:0 1px 2px rgb(0 0 0 / .06);--c-pop:0 12px 32px rgb(0 0 0 / .14);--c-tt:none;--c-ls:0;--c-fw:500;--c-fs:14px;--c-ring:2px solid var(--primary);--c-ind:2px;color-scheme:light}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]){--bg:#10151a;--surface:#20262e;--border:#363d45;--text:#eff1f4;--muted:#aab2bc;--primary:#70aefd;--on-primary:#111111;--accent:#b9bbff;color-scheme:dark}
}
:root[data-theme="dark"]{--bg:#10151a;--surface:#20262e;--border:#363d45;--text:#eff1f4;--muted:#aab2bc;--primary:#70aefd;--on-primary:#111111;--accent:#b9bbff;color-scheme:dark}
/* Component */
.mgd-sr{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.mgd-side-demo{display:grid;grid-template-columns:auto 1fr;min-height:540px;border:1px solid var(--border);border-radius:14px;overflow:hidden;background:var(--bg)}
.mgd-side{width:248px;display:flex;flex-direction:column;gap:2px;padding:16px 12px;background:var(--surface);border-right:var(--c-bw) solid var(--border);transition:width .16s}
.mgd-side__top{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:2px 4px 14px}
.mgd-side__brand{display:flex;align-items:center;gap:10px;font:700 16px var(--font-h);white-space:nowrap;overflow:hidden}
.mgd-side__mark{flex:none;width:26px;height:26px;border-radius:var(--c-r);background:var(--primary)}
.mgd-side__collapse{flex:none;width:34px;height:34px;display:grid;place-items:center;border:1px solid var(--muted);border-radius:var(--c-pill);background:var(--bg);color:var(--text);cursor:pointer}
.mgd-side__collapse:hover{background:color-mix(in oklab,var(--primary) 10%,var(--bg))}
.mgd-side ul{list-style:none;margin:0;padding:0;display:grid;gap:2px}
.mgd-side__link{display:flex;align-items:center;gap:12px;width:100%;min-height:40px;padding:0 10px;border:0;border-radius:var(--c-r);background:none;color:var(--muted);font:500 14px/1 var(--font-b);text-transform:var(--c-tt);letter-spacing:var(--c-ls);text-decoration:none;text-align:left;white-space:nowrap;cursor:pointer;transition:background-color .12s,color .12s}
.mgd-side__link:hover,.mgd-side__link.is-hover{background:color-mix(in oklab,var(--primary) 9%,transparent);color:var(--text)}
.mgd-side__link:focus-visible,.mgd-side__link.is-focus,.mgd-side__collapse:focus-visible{outline:var(--c-ring);outline-offset:-2px}
.mgd-side__link[aria-current="page"],.mgd-side__link.is-on{color:var(--text);font-weight:600;background:color-mix(in oklab,var(--primary) 15%,transparent);box-shadow:inset 3px 0 0 var(--primary)}
.mgd-side__link[aria-disabled="true"],.mgd-side__link.is-off{opacity:.45;cursor:not-allowed;background:none}
.mgd-side__count{margin-left:auto;min-width:22px;height:20px;padding:0 6px;display:inline-grid;place-items:center;border-radius:999px;background:var(--text);color:var(--bg);font:700 11px/1 var(--font-b);letter-spacing:0}
.mgd-side__chev{margin-left:auto;transition:transform .14s}
.mgd-side__link[aria-expanded="true"] .mgd-side__chev{transform:rotate(180deg)}
.mgd-side__sub{padding-left:28px!important}
.mgd-side__sub[hidden]{display:none!important}
.mgd-side__sub .mgd-side__link{min-height:34px;font-size:13px}
.mgd-side__label{overflow:hidden;text-overflow:ellipsis}
.mgd-side__foot{margin-top:auto;padding-top:12px;border-top:1px solid var(--border)}
.mgd-side.is-collapsed{width:68px}
.mgd-side.is-collapsed .mgd-side__top{flex-direction:column}
.mgd-side.is-collapsed .mgd-side__label,.mgd-side.is-collapsed .mgd-side__brand span,.mgd-side.is-collapsed .mgd-side__chev,.mgd-side.is-collapsed .mgd-side__sub{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0)}
.mgd-side.is-collapsed .mgd-side__count{position:absolute;margin:-18px 0 0 14px;min-width:16px;height:16px;font-size:10px}
.mgd-side.is-collapsed .mgd-side__link{justify-content:center;padding:0}
.mgd-side-main{padding:28px}
.mgd-side-main h3{margin:0 0 6px;font:var(--hw) 22px/1.2 var(--font-h)}
.mgd-side-main p{margin:0;color:var(--muted)}
@media (max-width:640px){.mgd-side-demo{grid-template-columns:1fr}
.mgd-side{width:auto;border-right:0;border-bottom:var(--c-bw) solid var(--border)}
.mgd-side.is-collapsed{width:auto}
.mgd-side-main{padding:18px}}
@media (prefers-reduced-motion:reduce){.mgd-side,.mgd-side *{transition:none!important;animation-duration:2.4s!important}}document.querySelectorAll(".mgd-side").forEach(function (nav) {
nav.addEventListener("click", function (e) {
var b = e.target.closest("button[aria-expanded]"); if (!b) return;
var open = b.getAttribute("aria-expanded") !== "true";
b.setAttribute("aria-expanded", open);
if (b.classList.contains("mgd-side__collapse")) { nav.classList.toggle("is-collapsed", !open); b.setAttribute("aria-label", open ? "Collapse sidebar" : "Expand sidebar"); }
else document.getElementById(b.getAttribute("aria-controls")).hidden = !open;
});
});## Component: Sidebar navigation
A vertical app navigation with a current page, a collapsible group and a collapse-to-icons button.
- **Pattern:** WAI-ARIA Authoring Practices, Disclosure (navigation menu) (https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/)
- **Roles and attributes:** <nav aria-label="Main"> with a list of links; the current page has aria-current="page"; a group header is a button with aria-expanded and aria-controls (disclosure pattern); the collapse button has aria-expanded and aria-controls, and icon-only links keep their text for screen readers.
- **States drawn:** default, hover, focus-visible, selected, disabled
- **Focus:** a visible `:focus-visible` outline (2px solid primary), never removed
- **Style knobs (minimal):** border 1px, corners 8px, shadow `0 1px 2px rgb(0 0 0 / .06)`, labels sentence case
- **Motion:** transitions are short (≤160ms) and switched off under `prefers-reduced-motion: reduce`
- **Code:** HTML + CSS + a few lines of plain JavaScript (no libraries); colours come only from the tokens above, so light and dark both work
### Keyboard
- **Tab:** move between links and buttons
- **Enter / Space:** open or close a group, or collapse the sidebar
### Licence
Original Made Good Designs code: free to use and adapt in any project, including commercial ones, with no credit needed. Fonts are Google Fonts under their own licences.Add the Made Good Designs library to your assistant once. Then ask for UI references, brand palettes, font pairings and design tokens in any chat.
https://madegooddesigns.com/inspiration/mcp?ref=ui-sidebar-navigation-uiSettings → Connectors → Add custom connector → paste the URL.
Settings → Apps & Connectors → Advanced → Developer mode → Create → paste the URL.
One click, then confirm in Cursor.
One click, then confirm in VS Code (Copilot agent mode).
claude mcp add --transport http made-good-designs https://madegooddesigns.com/inspiration/mcp?ref=ui-sidebar-navigation-ui
gemini mcp add --transport http made-good-designs https://madegooddesigns.com/inspiration/mcp?ref=ui-sidebar-navigation-ui
Add this to the app's MCP config (Windsurf: mcp_config.json).
Fonts: Inter (Google Fonts)
Prompt copied: paste it into the chat that just opened.
Writing about this component?
search_ui_screens (e.g. “billing settings, editorial style”), get_ui_flow for a whole journey, and get_ui_screen_code to pull the HTML and DESIGN.md straight into your project.