Using Electron.js, creating a custom "System Bar" for your application makes it visually more appealing. I always customize this area according to the design for every application I develop. I wanted to share this here so that it can be readily available.
Vue Component
Let's create our component for the System Bar and arrange it as follows:
<template>
<q-header class="titlebar bg-accent">
<q-toolbar>
<q-toolbar-title
class="flex items-center no-wrap text-body1 text-weight-medium text-primary"
>
<q-icon name="fingerprint" left size="md" />
Desktop App
</q-toolbar-title>
<q-space></q-space>
<q-btn
round
size=".53rem"
color="primary"
unelevated
class="titlebar-button q-mr-sm"
@click="minimizeWindow"
>
<q-icon name="remove" class="text-weight-bold"></q-icon>
</q-btn>
<q-btn
round
size=".53rem"
color="primary"
unelevated
class="titlebar-button q-mr-sm"
@click="maximizeWindow"
>
<q-icon
v-show="!isMaximized"
name="filter_none"
class="text-weight-bold"
></q-icon>
<q-icon
v-show="isMaximized"
name="crop_square"
class="text-weight-bold"
></q-icon>
</q-btn>
<q-btn
round
size=".53rem"
color="primary"
unelevated
class="titlebar-button"
@click="closeWindow"
>
<q-icon name="close" class="text-weight-bold"></q-icon>
</q-btn>
</q-toolbar>
</q-header>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
import { Platform } from 'quasar';
declare global {
interface Window {
WindowAPI: {
isMaximized: () => boolean;
minimize: () => void;
toggleMaximize: () => void;
close: () => void;
};
}
}
const isMaximized = Platform.is.electron ? window.WindowAPI.isMaximized : () => false;
export default defineComponent({
name: 'SystemBar',
data: () => ({
isMaximized: !isMaximized(),
restore: false
}),
methods: {
minimizeWindow() {
window.WindowAPI.minimize();
},
maximizeWindow() {
this.isMaximized = isMaximized();
window.WindowAPI.toggleMaximize();
},
closeWindow() {
window.WindowAPI.close();
}
}
});
</script>
<style scoped>
.titlebar {
-webkit-user-select: none;
-webkit-app-region: drag;
}
.titlebar-button {
-webkit-app-region: no-drag;
}
</style>
Here, the CSS code is important because if not set correctly, it will not perform the various functions you add. For example, the -webkit-app-region: drag;
property allows you to drag the window when clicking and holding on it with the mouse. The -webkit-app-region: no-drag;
property excludes certain areas or functions (buttons, links) from the dragging action.
Disable Default Frame
By default, we will remove the system bar. In src-electron/electron-main.js
, add the frame: false
value to the area defined as mainWindow = new BrowserWindow({
function createWindow() {
/**
* Initial window options
*/
mainWindow = new BrowserWindow({
icon: path.resolve(__dirname, 'icons/icon.png'), // tray icon
width: 1500,
height: 850,
minWidth: 450,
// `frame` option,
frame: false,
useContentSize: true,
webPreferences: {
...
Electron Middleware
Next, in src-electron/electron-preload.js
, we add the following code. Here, the operations performed are considered a middleware between Electron and Vue. Through contextBridge
, we provide a new object that we will use in our Vue project.
import { BrowserWindow } from '@electron/remote';
// Window actions
contextBridge.exposeInMainWorld('WindowAPI', {
isMaximized() {
const win = BrowserWindow.getFocusedWindow();
return win?.isMaximized();
},
minimize() {
BrowserWindow.getFocusedWindow()?.minimize();
},
toggleMaximize() {
const win = BrowserWindow.getFocusedWindow();
if (win?.isMaximized()) {
win.unmaximize();
} else {
win?.maximize();
}
},
close() {
BrowserWindow.getFocusedWindow()?.close();
}
});
Thus, we have customized the System Bar part of our application.
🔥 Comments