JavaScript menus for native-looking applications

Using web technologies for the GUI of a desktop application makes a lot of sense: they're portable, familiar, and powerful. A popular option is to use a comprehensive framework such as Electron. However, you might want the option of using a regular desktop browser — maybe you want to be able to access your application remotely, or you might prefer a lighter-weight embedded browser such as webview.

For a native-looking application you probably want menus: a top menubar as well as a pop-up (context) menu. While the various embedded platforms (such as Electron) each have their own APIs for menus, there is no standard JavaScript API. The DomTerm terminal emulator can be run with a small Electron wrapper (in which case it uses Electron menus), but it can also run in a plain browser like Firefox or Chrome. So I looked around for a lightweight menu library that would work in a desktop browser, but I didn't find anything I liked: They were unmaintained, or too big, or depended on some other library (such as jQuery), or were incomplete (popup menus but no menubar support, or missing keyboard navigation), or had an API too different from Electron's relatively simple one.

I finally found Sam Wray's nwjs-menu-browser, which satisfied most of the goals. It was strandalone, modest size, handled menubars as well as popups, and had an API similar to NW.js (which is similar to that of Electron). However, it had some issues. Missing features included keyboard navigation, inability to share menu-items between menus, and some smaller problems. I also found the build process too complicated for me.

The jsMenus library is a much-changed fork of nwjs-menu-browser. The functionality (and API) are very similar to that of Electron. In fact DomTerm uses much of the same JavaScript to construct menus whether using Electron or jsMenus. To see most of the features in action, check this live demo. It should be easy to figure out how it works from the demo.html source. You can also read the API documentation.

Finally, here is screenshot of jsMenus in action. This is DomTerm, using the Chrome browser. Chrome was started with the --app command-line option, which (among other things) disables the default menubar and location bar.