<nav class="wf-navbar" data-wf-navbar>
<div class="wf-navbar-inner">
<!-- Brand -->
<a class="wf-navbar-brand" href="/">
<div class="wf-navbar-brand-logo"><i class="icon wojo" aria-hidden="true"></i></div>
Wojo
</a>
<!-- Mobile hamburger -->
<button class="wf-navbar-hamburger" data-wf-navbar-toggle
aria-expanded="false" aria-label="Open menu">
<i class="icon menu" aria-hidden="true"></i>
</button>
<!-- Drawer -->
<div class="wf-navbar-menu" data-wf-navbar-menu>
<!-- Mobile-only drawer header -->
<div class="wf-navbar-menu-header">
<a class="wf-navbar-brand" href="/">...</a>
<button class="wf-navbar-hamburger" data-wf-navbar-toggle aria-expanded="false"
aria-label="Close menu">
<i class="icon cancel" aria-hidden="true"></i>
</button>
</div>
<!-- Left items -->
<div class="wf-navbar-start">
<a class="wf-navbar-item" href="/" aria-current="page">Home</a>
<a class="wf-navbar-item" href="/features">Features</a>
</div>
<!-- Right items -->
<div class="wf-navbar-end">
<a class="wf-navbar-item" href="/login">Sign in</a>
<a class="wf-btn wf-btn-sm" href="/signup">Get started</a>
</div>
</div>
</div>
</nav>
Navbar
Responsive navbar with brand, plain links, dropdown groups, full-width mega menus, and a slide-in mobile drawer. Auto-initialized on data-wf-navbar with a configurable breakpoint. Supports dark, primary, and transparent color themes, and sticky positioning.
Quick Start
The minimal structure is nav.wf-navbar[data-wf-navbar] → div.wf-navbar-inner containing a brand, a hamburger toggle, and a div.wf-navbar-menu[data-wf-navbar-menu] that holds wf-navbar-start and wf-navbar-end sections. Click the Products link below to see the dropdown.
Dropdown Group
Wrap a trigger button and a div.wf-navbar-dropdown in a div.wf-navbar-group[data-wf-navbar-group] . The script toggles an is-open class on the group and sets aria-expanded on the trigger. On desktop the dropdown is absolutely positioned below the trigger; on mobile it expands inline via a max-height transition. Add wf-navbar-chevron to a chevron icon inside the trigger to rotate it when open. The script auto-flips to wf-navbar-group--end (right-aligned panel) when the default left-aligned position would overflow the viewport.
<div class="wf-navbar-group" data-wf-navbar-group>
<!-- Trigger -->
<button class="wf-navbar-item" aria-expanded="false">
Company
<i class="icon chevron down wf-navbar-chevron" aria-hidden="true"></i>
</button>
<!-- Panel -->
<div class="wf-navbar-dropdown">
<div>
<a class="wf-navbar-dd-item" href="/about">
<i class="icon user" aria-hidden="true"></i> About
</a>
<a class="wf-navbar-dd-item" href="/blog">
<i class="icon mail" aria-hidden="true"></i> Blog
</a>
<hr class="wf-navbar-dd-divider">
<a class="wf-navbar-dd-item wf-active" href="/contact">Contact</a>
</div>
</div>
</div>
Mega Menu
Replace wf-navbar-dropdown with wf-navbar-mega and add wf-navbar-group--mega to the group to make a full-width panel that spans the entire navbar. Inside the panel, use wf-navbar-mega-inner as a centred grid container, wf-navbar-mega-col for each column, and wf-navbar-mega-item for each link. Each item can include an icon container ( wf-navbar-mega-icon ) and a text block ( wf-navbar-mega-content ) with a title and description. Add wf-navbar-mega-col--feature to give a column a subtle highlighted background. On mobile the mega panel collapses inline like a dropdown.
<div class="wf-navbar-group wf-navbar-group--mega" data-wf-navbar-group>
<button class="wf-navbar-item" aria-expanded="false">
Solutions
<i class="icon chevron down wf-navbar-chevron" aria-hidden="true"></i>
</button>
<div class="wf-navbar-mega">
<div class="wf-navbar-mega-inner">
<!-- Regular column -->
<div class="wf-navbar-mega-col">
<p class="wf-navbar-mega-label">Platform</p>
<a class="wf-navbar-mega-item" href="/analytics">
<div class="wf-navbar-mega-icon">
<i class="icon chart bar" aria-hidden="true"></i>
</div>
<div class="wf-navbar-mega-content">
<span class="wf-navbar-mega-title">Analytics</span>
<span class="wf-navbar-mega-desc">Real-time data & insights</span>
</div>
</a>
<a class="wf-navbar-mega-item" href="/reports">
<div class="wf-navbar-mega-icon">
<i class="icon file text" aria-hidden="true"></i>
</div>
<div class="wf-navbar-mega-content">
<span class="wf-navbar-mega-title">Reports</span>
<span class="wf-navbar-mega-desc">Scheduled & ad-hoc reports</span>
</div>
</a>
</div>
<!-- Highlighted feature column (hidden on mobile) -->
<div class="wf-navbar-mega-col wf-navbar-mega-col--feature">
<p class="wf-navbar-mega-label">What’s new</p>
<a class="wf-navbar-mega-item" href="/changelog">
<div class="wf-navbar-mega-content">
<span class="wf-navbar-mega-title">Changelog</span>
<span class="wf-navbar-mega-desc">Latest releases</span>
</div>
</a>
</div>
</div>
</div>
</div>
Mobile Drawer
Below the breakpoint (default 768 px) the hamburger button appears and the wf-navbar-menu becomes a fixed, slide-in side drawer. The hamburger button carries data-wf-navbar-toggle ; place a second one inside wf-navbar-menu-header as a close button. The script appends a wf-navbar-backdrop to <body> while the drawer is open — clicking the backdrop closes the drawer. Opening the menu also swaps the hamburger icon to a cancel icon automatically.
<!-- Hamburger (inside wf-navbar-inner, hidden on desktop) -->
<button class="wf-navbar-hamburger"
data-wf-navbar-toggle
aria-expanded="false"
aria-label="Open menu">
<i class="icon menu" aria-hidden="true"></i>
</button>
<!-- Slide-in drawer -->
<div class="wf-navbar-menu" data-wf-navbar-menu>
<!-- Sticky header inside the drawer -->
<div class="wf-navbar-menu-header">
<a class="wf-navbar-brand" href="#">Brand</a>
<button class="wf-navbar-hamburger" data-wf-navbar-toggle aria-label="Close menu">
<i class="icon cancel" aria-hidden="true"></i>
</button>
</div>
<div class="wf-navbar-start">
<!-- nav items, groups, etc. -->
</div>
<div class="wf-navbar-end">
<!-- actions, sign-in, etc. -->
</div>
</div>
<!-- Backdrop is injected by the script; no markup needed -->
Themes
Three built-in color themes are available as modifier classes on the wf-navbar root element. The default theme inherits --wf-surface as its background. All theme modifiers work by overriding the CSS custom properties on the root, so they automatically apply to all nested panels, items, and the mobile drawer.
<!-- Dark -->
<nav class="wf-navbar wf-navbar--dark" data-wf-navbar>...</nav>
<!-- Primary (brand color) -->
<nav class="wf-navbar wf-navbar--primary" data-wf-navbar>...</nav>
<!-- Transparent (no background or bottom border) -->
<nav class="wf-navbar wf-navbar--transparent" data-wf-navbar>...</nav>
Sticky
Add wf-navbar--sticky to pin the navbar to the top of the viewport using position: sticky; top: 0 . It combines with any theme modifier class.
<nav class="wf-navbar wf-navbar--sticky" data-wf-navbar>
...
</nav>
Data Attributes
All configuration is handled through HTML data attributes placed on the relevant elements. No JavaScript options object is required for typical usage.
| Attribute | Element | Description |
|---|---|---|
data-wf-navbar |
<nav> |
Initializes the component on this element. |
data-wf-navbar-menu |
.wf-navbar-menu |
Marks the slide-in drawer so the script can open/close it. |
data-wf-navbar-toggle |
.wf-navbar-hamburger |
Marks a button as a mobile drawer toggle. Can appear on multiple buttons (e.g., the top hamburger and the in-drawer close button). |
data-wf-navbar-group |
.wf-navbar-group |
Marks a container as a dropdown/mega group. The script toggles is-open on this element. |
data-wf-navbar-breakpoint |
[data-wf-navbar] |
Mobile breakpoint in pixels. Default: 768. Override with e.g. data-wf-navbar-breakpoint="1024".
|
CSS Properties
All token overrides are scoped to .wf-navbar so multiple navbars on the same page can have independent themes.
| Property | Default | Description |
|---|---|---|
--wf-nbar-bg |
var(--wf-surface) |
Background color of the navbar and its panels. |
--wf-nbar-border |
var(--wf-border) |
color used for the bottom border and panel borders. |
--wf-nbar-text |
var(--wf-text) |
Default text color for items and brands. |
--wf-nbar-muted |
var(--wf-text-muted) |
Muted text color used for mega column labels and chevrons. |
--wf-nbar-accent |
var(--primary-color) |
Accent color used for mega item icons. |
--wf-nbar-height |
3.5rem |
Height of the inner row and the mobile drawer header. |
--wf-nbar-item-hover |
var(--primary-color-inverted) |
Background color applied on item hover. |
--wf-nbar-active-text |
var(--primary-color) |
Text color for .wf-active and [aria-current=page] items. |
--wf-nbar-dd-shadow |
0 2px 8px … 0 8px 24px … |
Box shadow applied to dropdown and mega panels. |
--wf-nbar-dd-radius |
var(--wf-radius-5) |
Border radius for dropdown panels and the navbar root. |
--wf-nbar-z |
900 |
Z-index of the navbar. Backdrop is z - 2, mobile drawer is z - 1. |
--wf-nbar-speed |
.18s |
Transition duration for open/close animations and hover states. |
--wf-nbar-ease |
cubic-bezier(.4, 0, .2, 1) |
Easing function for open/close transitions. |
Programmatic API
Each initialized navbar exposes an instance on el._wfNavbar . All methods can also be called on a manually created instance.
| Method | Description |
|---|---|
openMobile() |
Open the mobile slide-in drawer. No-op if already open. |
closeMobile() |
Close the mobile drawer and remove the backdrop. No-op if already closed. |
closeAll() |
Close all open dropdown and mega-menu groups. |
destroy() |
Remove all event listeners, close the mobile drawer, and remove the instance reference from the element. |
// Auto-init instance (set during DOMContentLoaded)
const nav = document.querySelector('[data-wf-navbar]')._wfNavbar
nav.openMobile()
nav.closeMobile()
nav.closeAll()
nav.destroy()
// Manual init
import { WojoNavbar } from '/assets/js/wf-production.min.js'
const instance = new WojoNavbar(nav, { breakpoint: 1024 }).init()
Events
All events are dispatched on the navbar root element and bubble normally. Group events include the group element in event.detail .
| Event | Detail | Description |
|---|---|---|
wf:navbar-open |
{ group } |
Fired when a dropdown or mega group opens. |
wf:navbar-close |
{ group } |
Fired when a dropdown or mega group closes. |
wf:navbar-mobile-open |
— | Fired when the mobile slide-in drawer opens. |
wf:navbar-mobile-close |
— | Fired when the mobile slide-in drawer closes. |
const nav = document.querySelector('[data-wf-navbar]')
nav.addEventListener('wf:navbar-open', e => {
console.log('Group opened:', e.detail.group)
})
nav.addEventListener('wf:navbar-mobile-open', () => {
document.body.classList.add('no-scroll')
})
nav.addEventListener('wf:navbar-mobile-close', () => {
document.body.classList.remove('no-scroll')
})
Class Reference
All modifier classes available on .wf-navbar
| Class | Description |
|---|---|
wf-navbar |
Root navbar element. Defines all CSS custom properties. |
wf-navbar--dark |
Dark background theme modifier. |
wf-navbar--primary |
Primary (brand) color theme modifier. |
wf-navbar--transparent |
Removes the background and bottom border. |
wf-navbar--sticky |
Pins the navbar to the top of the viewport (position: sticky). |
wf-navbar-inner |
Flex row inside the navbar that holds brand, hamburger, and menu. |
wf-navbar-brand |
Brand/logo link. Also used as the title inside the mobile drawer header. |
wf-navbar-brand-logo |
Square icon box element placed inside the brand link. |
wf-navbar-hamburger |
Hamburger / close toggle button. Hidden on desktop, visible on mobile. |
wf-navbar-menu |
Slide-in drawer wrapper on mobile; flex row on desktop. |
wf-navbar-menu-header |
Sticky header shown at the top of the mobile drawer. Hidden on desktop. |
wf-navbar-start |
Left-aligned section for navigation links and groups. |
wf-navbar-end |
Right-aligned (auto-margin) section for sign-in links and action buttons. |
wf-navbar-item |
A nav link or group trigger button. Apply wf-active or aria-current="page" for the active state.
|
wf-navbar-chevron |
Icon inside a group trigger that rotates 180° when the group is open. |
wf-navbar-group |
Dropdown group wrapper. Add data-wf-navbar-group to activate. |
wf-navbar-group--end |
Right-aligns the dropdown panel. Auto-applied by JS when left-aligned would overflow; can be set manually. |
wf-navbar-group--mega |
Makes the group use a full-width mega panel instead of a dropdown. |
wf-navbar-dropdown |
Absolutely positioned dropdown panel. Contains a single <div> flex column.
|
wf-navbar-dd-item |
Link row inside a dropdown panel. Add wf-active to highlight the current page. |
wf-navbar-dd-divider |
Horizontal rule divider between dropdown items. Hidden on mobile. |
wf-navbar-mega |
Full-width mega panel. Spans the full width of the navbar on desktop. |
wf-navbar-mega-inner |
Centred auto-fit grid container inside the mega panel. |
wf-navbar-mega-col |
Single column inside the mega grid. |
wf-navbar-mega-col--feature |
Highlighted column variant with a subtle surface background. Hidden on mobile. |
wf-navbar-mega-label |
Small all-caps column heading inside a mega column. |
wf-navbar-mega-item |
Link row inside a mega column. Typically, contains an icon and content block. |
wf-navbar-mega-icon |
Square icon container inside a mega item. |
wf-navbar-mega-content |
Text wrapper inside a mega item, containing a title and description. |
wf-navbar-mega-title |
Bold item title inside wf-navbar-mega-content. |
wf-navbar-mega-desc |
Muted description line inside wf-navbar-mega-content. |
wf-navbar-backdrop |
Blurred overlay injected into <body> by JS while the mobile drawer is open.
|
is-open |
State class added by JS to [data-wf-navbar-group] when open, and to .wf-navbar-menu when the mobile drawer is open.
|
is-visible |
State class added by JS to .wf-navbar-backdrop to trigger the fade-in transition.
|