JavaScript Navigation Menu
The jSuites Menu is a lightweight JavaScript plugin for building responsive sidebar navigation menus. It features collapsible folders, automatic URL-based selection, smooth animations, and transforms into a mobile-friendly slide-out panel on smaller screens. It works seamlessly with React, Angular, Vue, or vanilla JavaScript.
Documentation
Section titled “Documentation”Methods
Section titled “Methods”| Method | Description |
|---|---|
| show() | Display the menu (with slide animation on mobile) |
| hide() | Hide the menu (with slide animation on mobile) |
| toggle() | Toggle menu visibility |
| load() | Load the menu and apply initial selection based on current URL |
| update(adjustScroll?: boolean) | Update the selected state based on the current URL path |
| select(element, event) | Programmatically select a menu item |
Events
Section titled “Events”| Event | Description |
|---|---|
| onclick | Fired when a menu link is clicked. onclick(instance: Object, event: MouseEvent) => void |
| onload | Fired when the menu finishes initializing. onload(element: HTMLElement, instance: Object) => void |
Initialization Properties
Section titled “Initialization Properties”| Property | Description |
|---|---|
| adjustOnLoad: boolean | Auto-scroll to selected item when menu loads. Default: true |
CSS Classes
Section titled “CSS Classes”| Class | Description |
|---|---|
| .jmenu | Main menu container (added automatically) |
| .jmenu-logo | Logo image, visible only on mobile |
| .jmenu-icon | Menu toggle button (hamburger icon) |
| .folder | Collapsible section header |
| .selected | Applied to active folder and list item |
CSS Custom Properties
Section titled “CSS Custom Properties”| Property | Description |
|---|---|
| --main-color | Accent color for selected item border |
| --main-color-light | Background color for selected item |
Examples
Section titled “Examples”Basic Navigation Menu
Section titled “Basic Navigation Menu”Create a simple sidebar navigation with collapsible folders and automatic URL-based selection.
<html>
<script src="https://jsuites.net/v6/jsuites.js"></script>
<link rel="stylesheet" href="https://jsuites.net/v6/jsuites.css" type="text/css" />
<script src="https://cdn.jsdelivr.net/npm/@jsuites/menu/menu.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jsuites/menu/menu.min.css" type="text/css" />
<button class="jmenu-icon" id="menu-toggle">Menu</button>
<div id="navigation">
<img src="/logo.png" class="jmenu-logo" />
<nav>
<h2 data-icon="home" class="folder">Getting Started</h2>
<div>
<ul>
<li><a href="/docs">Introduction</a></li>
<li><a href="/docs/getting-started">Installation</a></li>
<li><a href="/docs/changelog">Changelog</a></li>
</ul>
</div>
</nav>
<nav>
<h2 data-icon="code" class="folder">Components</h2>
<div>
<ul>
<li><a href="/docs/javascript-calendar">Calendar</a></li>
<li><a href="/docs/dropdown">Dropdown</a></li>
<li><a href="/docs/color-picker">Color Picker</a></li>
</ul>
</div>
</nav>
</div>
<script>
const navigation = menu(document.getElementById('navigation'), {
adjustOnLoad: true,
onclick: function(instance, e) {
console.log('Menu item clicked');
}
});
document.getElementById('menu-toggle').addEventListener('click', function() {
navigation.toggle();
});
</script>
</html>import { useRef, useEffect } from 'react';
import menu from '@jsuites/menu';
import '@jsuites/menu/menu.css';
function App() {
const menuRef = useRef(null);
const containerRef = useRef(null);
const sections = [
{
title: 'Getting Started',
icon: 'home',
links: [
{ href: '/docs', title: 'Introduction' },
{ href: '/docs/getting-started', title: 'Installation' },
{ href: '/docs/changelog', title: 'Changelog' }
]
},
{
title: 'Components',
icon: 'code',
links: [
{ href: '/docs/javascript-calendar', title: 'Calendar' },
{ href: '/docs/dropdown', title: 'Dropdown' },
{ href: '/docs/color-picker', title: 'Color Picker' }
]
}
];
useEffect(() => {
if (containerRef.current) {
menuRef.current = menu(containerRef.current, {
adjustOnLoad: true,
onclick: (instance, e) => {
console.log('Menu item clicked');
}
});
}
}, []);
const handleToggle = () => {
menuRef.current?.toggle();
};
return (
<>
<button className="jmenu-icon" onClick={handleToggle}>Menu</button>
<div ref={containerRef}>
<img src="/logo.png" className="jmenu-logo" />
{sections.map((section, index) => (
<nav key={index}>
<h2 data-icon={section.icon} className="folder">{section.title}</h2>
<div>
<ul>
{section.links.map((link, i) => (
<li key={i}><a href={link.href}>{link.title}</a></li>
))}
</ul>
</div>
</nav>
))}
</div>
</>
);
}
export default App;<template>
<button class="jmenu-icon" @click="toggle">Menu</button>
<div ref="menuContainer">
<img src="/logo.png" class="jmenu-logo" />
<nav v-for="(section, index) in sections" :key="index">
<h2 :data-icon="section.icon" class="folder">{{ section.title }}</h2>
<div>
<ul>
<li v-for="(link, i) in section.links" :key="i">
<a :href="link.href">{{ link.title }}</a>
</li>
</ul>
</div>
</nav>
</div>
</template>
<script>
import menu from '@jsuites/menu';
import '@jsuites/menu/menu.css';
export default {
name: 'App',
data() {
return {
menuInstance: null,
sections: [
{
title: 'Getting Started',
icon: 'home',
links: [
{ href: '/docs', title: 'Introduction' },
{ href: '/docs/getting-started', title: 'Installation' },
{ href: '/docs/changelog', title: 'Changelog' }
]
},
{
title: 'Components',
icon: 'code',
links: [
{ href: '/docs/javascript-calendar', title: 'Calendar' },
{ href: '/docs/dropdown', title: 'Dropdown' },
{ href: '/docs/color-picker', title: 'Color Picker' }
]
}
]
};
},
mounted() {
this.menuInstance = menu(this.$refs.menuContainer, {
adjustOnLoad: true,
onclick: (instance, e) => {
console.log('Menu item clicked');
}
});
},
methods: {
toggle() {
this.menuInstance?.toggle();
}
}
};
</script>Nested Menu Structure
Section titled “Nested Menu Structure”Create a menu with subsections using h3 headings for additional grouping.
<html>
<script src="https://jsuites.net/v6/jsuites.js"></script>
<link rel="stylesheet" href="https://jsuites.net/v6/jsuites.css" type="text/css" />
<script src="https://cdn.jsdelivr.net/npm/@jsuites/menu/menu.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jsuites/menu/menu.min.css" type="text/css" />
<div id="nested-menu">
<nav>
<h2 data-icon="widgets" class="folder">Components</h2>
<div>
<h3>Form Elements</h3>
<ul>
<li><a href="/docs/javascript-mask">Mask</a></li>
<li><a href="/docs/javascript-tags">Tags</a></li>
<li><a href="/docs/rating">Rating</a></li>
</ul>
<h3>Layout</h3>
<ul>
<li><a href="/docs/javascript-tabs">Tabs</a></li>
<li><a href="/docs/modal">Modal</a></li>
</ul>
</div>
</nav>
</div>
<script>
menu(document.getElementById('nested-menu'), {
adjustOnLoad: true
});
</script>
</html>import { useRef, useEffect } from 'react';
import menu from '@jsuites/menu';
import '@jsuites/menu/menu.css';
function App() {
const containerRef = useRef(null);
useEffect(() => {
if (containerRef.current) {
menu(containerRef.current, {
adjustOnLoad: true
});
}
}, []);
return (
<div ref={containerRef}>
<nav>
<h2 data-icon="widgets" className="folder">Components</h2>
<div>
<h3>Form Elements</h3>
<ul>
<li><a href="/docs/javascript-mask">Mask</a></li>
<li><a href="/docs/javascript-tags">Tags</a></li>
<li><a href="/docs/rating">Rating</a></li>
</ul>
<h3>Layout</h3>
<ul>
<li><a href="/docs/javascript-tabs">Tabs</a></li>
<li><a href="/docs/modal">Modal</a></li>
</ul>
</div>
</nav>
</div>
);
}
export default App;<template>
<div ref="menuContainer">
<nav>
<h2 data-icon="widgets" class="folder">Components</h2>
<div>
<h3>Form Elements</h3>
<ul>
<li><a href="/docs/javascript-mask">Mask</a></li>
<li><a href="/docs/javascript-tags">Tags</a></li>
<li><a href="/docs/rating">Rating</a></li>
</ul>
<h3>Layout</h3>
<ul>
<li><a href="/docs/javascript-tabs">Tabs</a></li>
<li><a href="/docs/modal">Modal</a></li>
</ul>
</div>
</nav>
</div>
</template>
<script>
import menu from '@jsuites/menu';
import '@jsuites/menu/menu.css';
export default {
name: 'App',
mounted() {
menu(this.$refs.menuContainer, {
adjustOnLoad: true
});
}
};
</script>Update Selection on Route Change
Section titled “Update Selection on Route Change”When using client-side routing, update the menu selection when the URL changes.
<html>
<script src="https://jsuites.net/v6/jsuites.js"></script>
<link rel="stylesheet" href="https://jsuites.net/v6/jsuites.css" type="text/css" />
<script src="https://cdn.jsdelivr.net/npm/@jsuites/menu/menu.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jsuites/menu/menu.min.css" type="text/css" />
<div id="spa-menu">
<nav>
<h2 class="folder">Pages</h2>
<div>
<ul>
<li><a href="/">Home</a></li>
<li><a href="/docs">Docs</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
</div>
</nav>
</div>
<script>
const navigation = menu(document.getElementById('spa-menu'), {
adjustOnLoad: true
});
// Update selection when using browser back/forward
window.addEventListener('popstate', () => {
navigation.update(true); // true = scroll to selected item
});
// Call after programmatic navigation
function navigateTo(url) {
history.pushState(null, '', url);
navigation.update(true);
}
</script>
</html>import { useRef, useEffect } from 'react';
import { useLocation } from 'react-router-dom';
import menu from '@jsuites/menu';
import '@jsuites/menu/menu.css';
function App() {
const menuRef = useRef(null);
const containerRef = useRef(null);
const location = useLocation();
useEffect(() => {
if (containerRef.current) {
menuRef.current = menu(containerRef.current, {
adjustOnLoad: true
});
}
}, []);
// Update selection when route changes
useEffect(() => {
menuRef.current?.update(true);
}, [location]);
return (
<div ref={containerRef}>
<nav>
<h2 className="folder">Pages</h2>
<div>
<ul>
<li><a href="/">Home</a></li>
<li><a href="/docs">Docs</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
</div>
</nav>
</div>
);
}
export default App;<template>
<div ref="menuContainer">
<nav>
<h2 class="folder">Pages</h2>
<div>
<ul>
<li><a href="/">Home</a></li>
<li><a href="/docs">Docs</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
</div>
</nav>
</div>
</template>
<script>
import menu from '@jsuites/menu';
import '@jsuites/menu/menu.css';
export default {
name: 'App',
data() {
return {
menuInstance: null
};
},
mounted() {
this.menuInstance = menu(this.$refs.menuContainer, {
adjustOnLoad: true
});
},
watch: {
'$route'() {
this.menuInstance?.update(true);
}
}
};
</script>Responsive Behavior
Section titled “Responsive Behavior”The menu automatically adapts for different screen sizes:
- Desktop (>800px): Static sidebar, folders expand/collapse in place
- Mobile (<800px):
- Full-height slide-out panel with fixed positioning
- Logo becomes visible (
.jmenu-logo) - Close button appears in top-right corner
- Clicking a link automatically closes the menu
HTML Structure
Section titled “HTML Structure”The menu expects the following HTML structure:
<div id="menu">
<!-- Optional logo for mobile view -->
<img src="/logo.png" class="jmenu-logo" />
<nav>
<!-- Collapsible folder header with optional icon -->
<h2 data-icon="icon_name" class="folder">Section Title</h2>
<div>
<!-- Optional subsection heading -->
<h3>Subsection</h3>
<ul>
<li><a href="/path">Link Text</a></li>
</ul>
</div>
</nav>
</div>
Related Tools
Section titled “Related Tools”- JavaScript Context Menu - Right-click context menus for actions and options