Skip to main content
WebviewJS uses muda to render fully native menu bars on each platform. Menus can be global (app-level, shared across all windows) or per-window (overriding the global menu for a specific window). All menu item click events are delivered to your Node.js process via the custom-menu-click application event.

Setting a global menu

Call app.setMenu(MenuOptions) to attach a menu bar to the running application. The call is safe to make before or after windows are created.
setMenu() is additive — calling it a second time replaces the current menu entirely. Pass null to remove the menu bar.

Handling menu clicks

Listen for the custom-menu-click application event to respond to clicks on any menu item that has an id. The payload contains a customMenuEvent object with the clicked item’s identifier and the ID of the window it originated from.
Items that use a role (e.g. copy, quit) are handled natively and do not emit custom-menu-click.

Updating menus at runtime

Replace the active menu at any time by calling app.setMenu() again with a new MenuOptions object. The menu bar updates immediately on Windows and macOS.
To remove the menu bar entirely, pass null:

Per-window menus

Call win.setMenu(MenuOptions) to attach a menu that overrides the global menu for that specific window. All other windows continue to use the global menu.
Per-window menu clicks also fire custom-menu-click on app. Use customMenuEvent.windowId to tell which window originated the click.
Every entry in a submenu.items array is a MenuItemOptions object.

Predefined roles

Roles map menu items to native platform actions and are automatically localised into the system language. You do not need to supply label, id, or accelerator for role items.

Keyboard accelerators

An accelerator string defines a keyboard shortcut displayed next to the menu label. The format is a +-separated list of modifiers followed by a key name. Examples

Nested submenus

Set the submenu field on any menu item to create a hierarchical menu structure. Nesting depth is limited only by the platform’s native rendering.
When an item has a submenu, the id and accelerator fields on that parent item are ignored — only label and enabled apply.

Platform differences