Electron, v3

Menubar & System Tray Apps

Steve Kinney

Steve Kinney

Electron, v3

Check out a free preview of the full Electron, v3 course

The "Menubar & System Tray Apps" Lesson is part of the full, Electron, v3 course featured in this preview video. Here's what you'd learn in this lesson:

Steve walks through how to display an application icon in the menubar and system tray. How to add a context menu to the menubar icon is also covered in this segment.


Transcript from the "Menubar & System Tray Apps" Lesson

>> So, let's make this a menu bar icon, right, or at least there's two pieces to this. There is the ability to add stuff to what is called a system tray in Windows and probably Linux, and the menu bar in MacOS. It'd be cool if we could put icons in there as well.

For those of you watching the live stream, I had to make one change and push something up. For those of you watching the recording this never happened and everything will be okay from the very beginning because of the magic of Git. So I have these two icons, and one thing I do wanna point out Is that the name is somewhat important here.

And I will explain why in a second. But I have these two icons. And there are some rules about getting it to fit in. Generally speaking, you want, I believe, depending on the OS, it's somewhere between 16 and 18 pixels, whether it's the Windows system tray or the Mac menu bar, and then it also depends on what version.

I just tend to go with 18 by 18. It has not failed me or wronged me in any way, shape, or form. The one thing that I want to draw to your attention is that it is, at least on MacOS, critically important that it ends in Template.png. Because that is meaningful to MacOS.

Furthermore, if one would like to do this and make sure that it ends in Template.png, it is critically important that it have exclusively one grayscale color, right? Now if one's gonna live a life like that, might I suggest white or black? But it doesn't really matter, it just matters that it is exclusively one grayscale color, PNG, and that it ends in Template.

The reason for this is, as long as you follow those rules, you do not need to make two different icons for light and dark mode, right? As long as there's one grayscale color and it ends in template, MacOS will make it white if it should be white, and it will make it black if it should be black, right?

If you deviate from this, it is now on you to read what mode the operating system is, what color the desktop background is. Good luck on that one, I don't even know how you did that one. So generally speaking, I would follow that rule if I were you and get all of this functionality for free.

I happen to use a white one at this point, I think in the folder for fire sale, it's a black one, just so I can make a point if I wanted to at some point, I don't really care to. But it will do the right thing on MacOS as long as you follow that heuristic.

With that, setting something up as a system tray or menu bar, you're seeing a recurring theme here, not that kind of tray. Which is you can pull in the tray module. I will let tray, ideally, hopefully, be a tray at some point or another. You could theoretically try to keep it bound to the window and app ready.

I guess I could probably just do this app ready, but you'll probably. I say probably, I've never thought about whether or not you could have three menu bar icons from the same app cuz I've never wanted to do that before in my life. Sometimes when you're teaching people, you realize that's a question I might get asked in about three minutes that independently as a person trying to build something for a reason had never occurred to me.

But you start to wonder these questions that you're gonna ask about a second in advance. I don't know. I will leave that as an exercise to the reader, probably. But I want one, and so I will kind of have that so I can use it for whatever I need to use it for.

And then I do need to wait for the application to be ready. At which point I can say, let tray = new tray. I don't think I have dirname in an ESM situation, so I just will. I happen to know that it's dots, cuz it's from the directory that you start the application from, is the process CWD.

I used to know the difference between dirname and process current working directory until ESM modules and node came out and dirname went away, and you have to get a URL in Git. I have written those functions in my apps once and use them everywhere. The variable is called __dirname and I treat it the same way, but I write that once per project, I have since long forgotten.

And this one is called tray template. Let's just start there. We don't need to let, we want the global one. Ideally, unless I have talked and opined on things changing underneath me whilst working. It looks like maybe I got something wrong there. Let's see, tray template, tray template, icons, there we go.

That's why we don't talk in code. And now you can see that it shows up in my menu bar as well. And you can do all sorts of stuff with this. You could theoretically throw a context menu on there and just have that show up. For instance, let's do that.

We could theoretically, let's say You can do tray on click, and you could have it theoretically, I don't know, show a context menu, something along those lines. In fact, let's do this, let's make a context menu which theoretically, you can IPC send over if they do a right-click in the render process.

Or you can use it on the tray, it's the same basic idea at this point. But we could theoretically just say const contextMenu. And let's go ahead and say menu. Gotta pull that in. .buildFromTemplate, like we saw the with application menu, cuz it's no different. It's just instead of being the application menu, it's a menu that you trigger programmatically at some point.

Whether that be on the context menu event in the DOM, or, in this case, I'm doing it from the main process as well. And we'll just say, I don't know, label, we'll just say open, I don't know, show window? Let's do show window, that feels good. We'll do show window, and, we'll say that when they click on it, sure, that seems great.

I love it. In fact, I'm just gonna do the same stuff that we saw previously and make sure that it's the focused window as well. And then, I don't know, let's do, what do you think, quit? I like quit, let's do that. Nobody agreed with me, but it's fine.

We can give that one the role of quit. Cool and then what we can do is we've got that menu in place, we've got our context menu. And then I can just do tray.setContextMenu to that contextMenu. Show window, quit. That's kinda cool, I guess, it's fine.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now