Electron, v3

Making a Menubar Application

Steve Kinney

Steve Kinney

Electron, v3

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

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

Steve demonstrates utilizing the "electron-positioner" library to show and hide the Clipmaster application similar to those of a menubar app.


Transcript from the "Making a Menubar Application" Lesson

>> What I want is something like this app, or this app, or this app, where I see the app, or I see a thing that I can interact with. This isn't fun, I want something like one of these, right, in place here. So there's a trick. Can you do that in Electron?

No, you cannot, sorry. Can you hide this window and then use a library to position it right about here? And then when this is clicked, show this window, and then hide it again? You can do that, [LAUGH] does that get us almost all of the way there? It does, right?

So we could turn this whole app into a menu bar app and do that instead, that feels like a thing that we could do. And that is, again, shockingly simple. I'm just making sure, there's a library that I might need to install, called electron-positioner. I have the types for it, all these dev dependencies are in the wrong order.

electron-positioner, which has a bunch of functionality, but most notably it's for positioning windows, and it's got a whole bunch of ways to do that. The ones that we care about in our time together here is I wanna put it right here, right? Where this menu ought to be, to give the illusion.

And I mean, I don't even know, who knows what these are, right? These could be Electron apps too, for all I know. I want to give the illusion that it is a peer to any one of these other applications. So let's go ahead and let's try that out.

And so, cool, we got that in place. I don't really need this context menu anymore, that was cool. And again, you can literally do the same when you right-click on something, have a custom menu. It is effectively, you request the menu through IPC, you send it back, you open it.

So we've got this onClick here that we can do stuff with. And so let's pull in electron-positioner in this case. And so what I'll do here is I'll say, import positioner. I think I want the full positioner, if I'm not mistaken, I'm doing that a little bit from memory.

So we've got, We've got positioner from, no, I might not have the right, yeah, it looks good. So by default, we will hide this window because we don't wanna show it anymore. And we wanna make sure I don't have that thing where it starts showing it for funzies.

Let's not ruin the surprise of the Dev Tools as well, and we kinda have that piece in place. I think I need this, it's a class, Positioner. No, let's look in here and find out what it is. It is a namespace, Electron Positioner, that is the default, so that's just the default export.

Cool, so we've got that in place, and now what we wanna do is we go in here and we say, positioner new Positioner for that browser window, in this case. And we also need the tray position. No, I didn't ask for a capital letter. Which one would do, on this positioner?

Yeah, you can see it's ruining the surprise a little bit here. Actually, you can do bottom right if you want. I want to calculate for my points, I want the trayCenter. So basically, what this does is it takes basically your window, which it knows the bounds of, to a certain extent.

And it takes, in this case, the tray, and it will figure out how to kind of change the x and y of that window. Why, IntelliSense, trayCenter. I need it from the tray.getBounds. Sweet, and we've gotta make sure we've declared that already. All right, so positioner wraps a browser window and has the ability to manipulate its location and size.

So that we also then find where it should be based on the center of our actual tray, which has a getBounds object, which is an Electron rectangle. It's doing the math for you, basically, where's the tray, where's the window? Put the window by the center of the tray, right?

That's a lot of words out of my mouth to do a relatively simple piece here. And then we just say browserWindow, we can set the position, what's that last argument, animate? We're gonna keep that as false for now, we might turn it to true so I can find out what that means.

I think you can watch it move, it should be hidden as it happens. Cool, and then we can say tray.onClick. And so when that happens, all we really wanna do at that point is we wanna say, there's no tray, cuz, We'll return, that's fine. If the main window is visible, then hide it, right?

Cuz we want it to toggle on and off. And there's not a toggle, per se, and you could write a function. If it's visible, hide it, otherwise, Could else, I, as a general rule, don't like else statements, but I'll just return, I can't live like this. Return, cool, and then we can, basically, cuz the thing can move based on where it moves.

So we've gotta move it again as well. I think we'll leave that there for now, though. We'll do main window, that should all be fine. I don't think this is gonna move in this case. I'm gonna keep it here for a second. I could choose to move this code down.

I'm gonna just do a mainWindow.show. Or browserWindow.show. All right, so this should, when I click on it, show. There is one other thing, it gets a little wonky, because there is a behavior we can double click on things in Windows. I think technically Mac OS too, so we're also just going to say tray., IgnoreDoubleClickEvents, otherwise, as you're trying to toggle it on and off, it gets super weird.

But that's a thing you can do as well, cuz you can listen to double-click events. No, we wanna, probably, let's choose to move it, When we're about to show it. Cool, and let's try that. Look at that, it feels like I got a menu bar out. It's nobody's business that I don't, cuz it feels like it.

And we saw before, you can actually hide all of this as well. And hide that top bar as well, and kind of do stuff along those lines, too, and kind of create a different feel. This app, I think you can actually pull this off as well, and do stuff like that too, but you can kinda get a little bit more nuanced.

But you can actually have this thing live in the menu bar, you could have it as something. You can kinda do some version where it maybe appears as a normal window, or have a menu, stuff along those lines, yeah.
>> And because we can have multiple different browser windows, we could have the intentional focus version and the quick bar version?

>> Yep, right now, I've always had this createWindow function, which is creating a window, setting a known preload script, and then pointing it at a known index.html. You can have multiple HTML files, you can have one for the menu bar icon, one for the full app, right? You can have them share the same preloaded scripts, so they have access to the same things.

Or maybe each one gets a different set of things if you're being super secure, right? You get a lot of flexibility in how you wanna manage, navigate, and orchestrate all these windows as well, yep. And then theoretically, you could hold on to references to the menu bar one as well as the main window.

And if something happens in one, the main process kind of broker the communication to one of the other windows as well, right? And so you can actually communicate between them simultaneously too, but, yeah. Awesome, so there's just one more slight thing we're gonna talk about towards the end here.

And we're gonna switch to one more app, which is just a super simple app that I'm just mostly gonna take you on a tour of, which is about using native modules, right? And just some of the tasting notes, it's a little bit more, we won't walk through it step by step.

But just to kinda look at what that looks like, and some of the nuances if you wanted to have a SQLite database to persist data instead of just the file system. It's a little bit more like, if you need it kinda thing, so we won't go all the way in, but kind of just showing what the different pieces around that too.

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