This module provides boilerplate for setting up a menubar application using Electron. All you have to do is point it at your index.html and menubar will handle the rest.
✅ Zero runtime dependencies, only one peer-dependency.
✅ Works on macOS, Windows and most Linuxes. See tested platforms.
✅ 💥 3.6kB minified + gzipped 💥
![]() |
![]() |
![]() |
|---|---|---|
| macOS Mojave 10.14 | Windows 10 | Ubuntu 18.04 |
bun add @gitify/menubarStarting with your own new project, run these commands:
$ bun add @gitify/menubar
$ touch myApp.js
$ touch index.htmlFill index.html with some HTML, and myApp.js like this:
const { menubar } = require('@gitify/menubar');
const mb = menubar();
mb.on('ready', () => {
console.log('app is ready');
// your app code here
});Then use electron to run the app:
$ electron myApp.jsAlternatively, see examples/hello-world folder for a simple working example.
The return value of menubar() is a Menubar class instance, which has these properties:
app: the Electron App instance,window: the Electron Browser Window instance,tray: the Electron Tray instance,positioner: thePositionerinstance used to compute the window's on-screen coordinates,setOption(option, value): change an option after menubar is created,getOption(option): get an menubar option,showWindow(): show the menubar window,hideWindow(): hide the menubar window,toggleWindow(): show the window if hidden, hide it if visible,recenterOnTray(): re-center the window over the tray icon,setContextMenu(menu): replace the tray context menu (auto-re-publishes on Linux),setGlobalShortcut(accelerator): register a global accelerator that toggles the window — returnsfalseon registration failure,destroy(): tear down the menubar instance,isDestroyed(): whether the menubar is currently destroyed.
You can pass an optional options object into the menubar({ ... }) function:
dir(defaultprocess.cwd()) - the app source directoryindex(defaultfile:// + opts.dir + index.html) - The URL to load the menubar's browserWindow with. The url can be a remote address (e.g.http://) or a path to a local HTML file using thefile://protocol.browserWindow- BrowserWindow options to be passed to the BrowserWindow constructor, see Electron docs. Some interesting fields to passed down are:x(defaultundefined) - the x position of the windowy(defaultundefined) - the y position of the windowwidth(default 400) - window widthheight(default 400) - window heightalwaysOnTop(default false) - if true, the window will not hide on blur
icon(defaultopts.dir + IconTemplate.png) - the png icon to use for the menubar. A good size to start with is 20x20. To support retina, supply a 2x sized image (e.g. 40x40) with@2xadded to the end of the name, soicon.pngandicon@2x.pngand Electron will automatically use your@2xversion on retina screens.tooltip(default empty) - menubar tray icon tooltip texttray(default created on-the-fly) - an electronTrayinstance. if providedopts.iconwill be ignoredpreloadWindow(default false) - Create BrowserWindow instance before it is used -- increasing resource usage, but making the click on the menubar load faster.loadUrlOptions- (default undefined) The options passed when loading the index URL in the menubar's browserWindow. Everything browserWindow.loadURL supports is supported; this object is simply passed onto browserWindow.loadURLshowOnAllWorkspaces(default true) - Makes the window available on all OS X workspaces.windowPosition(defaulttrayCenteron macOS/Linux,trayBottomCenteron Windows) - Sets the window position (browserWindow.x/browserWindow.ywill still override this). Valid values:trayLeft,trayBottomLeft,trayRight,trayBottomRight,trayCenter,trayBottomCenter,topLeft,topRight,bottomLeft,bottomRight,topCenter,bottomCenter,leftCenter,rightCenter,center.showDockIcon(default false) - Configure the visibility of the application dock icon.trigger(default'click') - Tray event that toggles the menubar window. One of'click','right-click', or'none'. Use'none'to disable automatic toggling — useful when a single tray icon serves multiple windows. The window can still be shown by callingmb.showWindow()directly.showOnRightClick(default false) - Deprecated, usetrigger: 'right-click'instead. Show the window on 'right-click' event instead of regular 'click'.contextMenu- An ElectronMenuto attach to the tray icon. On Linux it is bound viatray.setContextMenu(required by libappindicator / StatusNotifierItem) and re-published on every show/hide to defeat the indicator's menu cache. On macOS and Windows it pops up on right-click viatray.popUpContextMenu, so left-click continues to toggle the window. Combine withtrigger: 'none'if you want right-click to be the only interaction.hideOnClose(default false) - Hide the window oncloseinstead of destroying it, so the next tray click re-uses the sameBrowserWindow. On Linux/Wayland the hide is deferred viasetImmediateto work around a compositor bug that leaves frameless surfaces in a half-closed state when hidden synchronously from theclosehandler. The library tracks the app'sbefore-quitevent internally, so real quits go through unimpeded.escapeToHide(default false) - Hide the menubar window when the user pressesEscapewhile it has focus.ignoreDoubleClickEvents(default true, macOS only) - Callstray.setIgnoreDoubleClickEvents(true)so an accidental double-click doesn't race the close-on-blur handler and flicker the tray icon. Passfalseto opt out. No-op on Linux/Windows.globalShortcut- An Accelerator string registered as a global keyboard shortcut that toggles the menubar window. Unregistered automatically ondestroy(). Usemb.setGlobalShortcut(accelerator)to change or clear it at runtime.
The Menubar class is an event emitter:
ready- whenmenubar's tray icon has been created and initialized, i.e. whenmenubaris ready to be used. Note: this is different than Electron app'sreadyevent, which happens much earlier in the processcreate-window- the line beforenew BrowserWindow()is calledbefore-load- after create window, before loadUrl (can be used forrequire("@electron/remote/main").enable(webContents))after-create-window- the line after all window init code is done and url was loadedshow- the line beforewindow.show()is calledafter-show- the line afterwindow.show()is calledhide- the line beforewindow.hide()is called (on window blur)after-hide- the line afterwindow.hide()is calledafter-close- after the.window(BrowserWindow) property has been deletedfocus-lost- emitted if always-on-top option is set and the user clicks away
| menubar | Electron | Notes |
|---|---|---|
| 9.x.x | >=9.x.x | |
| 8.x.x | 8.x.xx | |
| 7.x.x | 7.x.xx | |
| 6.x.x | >=4.x.x <7.x.x | Not recommended for security reasons |
| <= 5.x.x | <= 3.x.x | Please, please don't use these old versions |
- Use
mb.on('after-create-window', callback)to run things after your app has loaded. For example you could runmb.window.openDevTools()to open the developer tools for debugging, or load a different URL withmb.window.loadURL() - Use
mb.on('focus-lost')if you would like to perform some operation when using the optionbrowserWindow.alwaysOnTop: true - To restore focus of previous window after menubar hide, use
mb.on('after-hide', () => { mb.app.hide() } )or similar - To attach a native context menu, pass it as
contextMenu:menubar({ contextMenu }). The library wires it viasetContextMenuon Linux andpopUpContextMenuon right-click on macOS/Windows so left-click still toggles the window. See this example for more information. - To avoid a flash when opening your menubar app, you can disable backgrounding the app using the following:
mb.app.commandLine.appendSwitch('disable-backgrounding-occluded-windows', 'true');
Originally created by Max Ogden — forked from maxogden/menubar.


