---
title: "JavaScript Menu"
description: "jSuites Menu is a lightweight JavaScript plugin for building responsive navigation menus with collapsible folders, automatic URL-based selection, and mobile-friendly slide-out sidebar functionality."
source: https://jsuites.net/docs/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

### 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

| Event     | Description                                                                                          |
|-----------|------------------------------------------------------------------------------------------------------|
| onclick   | Fired when a menu link is clicked. <br>`onclick(instance: Object, event: MouseEvent) => void`       |
| onload    | Fired when the menu finishes initializing. <br>`onload(element: HTMLElement, instance: Object) => void` |

### Initialization Properties

| Property                | Description                                              |
|-------------------------|----------------------------------------------------------|
| adjustOnLoad: boolean   | Auto-scroll to selected item when menu loads. Default: true |

### 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

| Property              | Description                           |
|-----------------------|---------------------------------------|
| --main-color          | Accent color for selected item border |
| --main-color-light    | Background color for selected item    |


## Examples

### Basic Navigation Menu

Create a simple sidebar navigation with collapsible folders and automatic URL-based selection.

```html
<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>
```
```jsx
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;
```
```vue
<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

Create a menu with subsections using `h3` headings for additional grouping.

```html
<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>
```
```jsx
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;
```
```vue
<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

When using client-side routing, update the menu selection when the URL changes.

```html
<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>
```
```jsx
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;
```
```vue
<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

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

The menu expects the following HTML structure:

{.ignore}
```html
<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

- [JavaScript Context Menu](/docs/contextmenu) - Right-click context menus for actions and options
