How to add custom menu in menubar in mac with electron?

18,020

Solution 1

There's great documentation on building native, custom application menus in the API docs here. There's lots of options and capabilities and platform differences.

For example, in your main process code you could do something like this:

const { app, BrowserWindow, Menu } = require('electron');
const path = require('path');
let mainWindow;

app.on('ready', () => {
  mainWindow = new BrowserWindow();
  mainWindow.loadURL(path.join('file://', __dirname, 'index.html'));
  setMainMenu();
});

function setMainMenu() {
  const template = [
    {
      label: 'Filter',
      submenu: [
        {
          label: 'Hello',
          accelerator: 'Shift+CmdOrCtrl+H',
          click() {
              console.log('Oh, hi there!')
          }
        }
      ]
    }
  ];
  Menu.setApplicationMenu(Menu.buildFromTemplate(template));
}

That will create an application level menu with the label "Filter" and when opened will display the single menu item labeled "Hello". Clicking on it logs to the console.

Note that when you're using electron-prebuilt, it always say "Electron" in the top left. When you compile your app as a standalone application (not running through electron-prebuilt), it'll have your app name there.

As @neonhomer pointed out, this API has to be called after the ready event of app module.

I should also add that when using Electron in development, the default Electron app will provide a default menu for you (see https://github.com/electron/electron/blob/d26e4a4abf9dfc277974c6c9678a24a5f9e4d104/default_app/main.js#L48). When you package your app, that won't be there.

Solution 2

There's a small note in the API documentation: http://electron.atom.io/docs/api/menu/#menusetapplicationmenumenu

Note: This API has to be called after the ready event of app module.

Interesting that it works called directly in Windows.

Here's a simplified example:

const {app, BrowserWindow, Menu} = require('electron')

const menuTemplate = [...]
const menu = Menu.buildFromTemplate(menuTemplate)

let win

function createWindow() {
    win = new BrowserWindow({ width: 800, height: 600, })

    win.loadURL(`file://${__dirname}/index.html`)

    win.on('closed', () => {
        win = null
    })
}

app.on('ready', () => {
    Menu.setApplicationMenu(menu)
    createWindow()
})

app.on('window-all-closed', () => {
    app.quit();
})

app.on('activate', () => {
    if (win === null) {
        createWindow()
    }
})
Share:
18,020
nirav jobanputra
Author by

nirav jobanputra

Updated on June 06, 2022

Comments

  • nirav jobanputra
    nirav jobanputra about 2 years

    I want to add custom menu in menu bar in mac with electron (nodejs)
    eg. we have
    enter image description here

    and I want to add filter menu right after Electron.

  • charles ross
    charles ross almost 8 years
    So far, this example has not worked for me on the Mac.Electron 1.2 on Yosemite.
  • Kramer
    Kramer over 7 years
    Something else interesting is that if a MenuItem is visible: false it still functions as a keyboard shortcut in Windows but does not on macOS.
  • vedi
    vedi over 7 years
    It does not work, you show draw attention at @neonhomer answer: "This API has to be called after the ready event of app module"
  • KuboAndTwoStrings
    KuboAndTwoStrings about 6 years
    For making sure it works well in both Mac and Windows, please add the following to the function scope where you add the template menu: ``` if(process.platform == 'darwin'){ template.unshift({}); } ```
  • Michael
    Michael almost 5 years
    I just want to add one menu item to the default menu... is there some way to do that without completely replacing it with an identical menu that I copy from the link you provided?