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.