Customizable Titlebar for frameless windows built with React

Customizable Titlebar for frameless windows built with React

Frameless Titlebar for Electron Applications.

Frameless Titlebar for Electron Applications

Customizable Titlebar for frameless windows built with React

Main

A lot of people like developing apps with the Electron framework because it's cross platform. On Windows however, Electron applications are often left untouched when it comes to the title bar. In my opinion, the default menu and title bar don't exaclty work well with some stylized applications such as Atom, VS Code or Signal. Apps would look a little more unified if they used a custom stylized menu. This is of course hugely inspired by the GitHub desktop application's menu bar.

Adding frameless-titlebar to your project

yarn add frameless-titlebar
# or
npm install frameless-titlebar

In your electron app.js file:

  // electron browser window set up
  mainWindow = new BrowserWindow({
    width: 1024,
    height: 728,
    // this is important since currently there is no support for scrollable menus
    minWidth: 600, // set a min width!
    minHeight: 300, // and a min height!
    // Remove the window frame from windows applications
    frame: false,
    // Hide the titlebar from MacOS applications while keeping the stop lights
    titleBarStyle: 'hidden', // or 'customButtonsOnHover',
  });

In your app's root container render method:

import TitleBar from 'frameless-titlebar';
import menu from './AppMenu'; // import your menu file
...
export default class App extends React.Component {
  ...
  render() {
    return (
      <div>
        <TitleBar
          icon={`${__dirname}/../resources/icon.png`}
          app="Electron"
          menu={menu}
        />
        {
          /* the rest of your application
          *  all your routes and stuff
          */
          this.props.children
        }
      </div>
    );
  }
}

Documentation

Menu Bar API (Windows)

// create a reference to the titlebar to access api methods
<TitleBar
  ref={r => { this.titleBar = r; }}
  ...
/>
// eg. change menu item's enabled property
this.titleBar.setKeyById('menuItemId1', 'enabled', false);

// or access the api methods via menuBar event property
[
  // menu item list
  {
    // menu item
    ...
    click: (item, win, e) => {
      e.menuBar.setKeyById(item.id, 'enabled', !item.enabled);
    }
  }
]
Name Params Description
setKeyById (id : string, key : string, value : any) Set a menu item's key properties using this method
getKeyById (id : string, key : string) Get the menu item properties for the menu item with the corresponding id. If no key is specified then the function will return the entire menuItem object

Titlebar properties

Name Type Platforms Description Default Value
icon string Windows The App Icon shown on the top left ''
app string All The app name shown to the left of the menu items on Windows applications. On Mac/Linux this will show in the center of the toolbar if the title property is not set ''
title string Mac The title shown in the center of mac applications, this will override the app property ''
menu array All The array of menu items following the Electron Menu Object Documentation/Template. See Supported Menu Item Properties []
theme object All Theme object to customize Titlebar See Theme

Supported Menu Item Properties

Name Type Description
id (optional) string Must be unique. If defined then it can be used as a reference to this item by the position attribute as well as the setKeyById
type (optional) oneOf([normal, separator, submenu, checkbox, radio]) Type of supported menu items
label (optional) string Menu item label
click (optional) function(menuItem, browserWindow, event) access the menu bar API with event.menuBar.apiMethodName()
enabled (optional) bool Enables/disables menu item from being clicked on
visible (optional) bool if false, hides menu item
sublabel (optional) string Menu item sublabel
accelerator (optional) string Accelerator string eg CmdOrCtrl+Z, note: as of now will only insert string literal and will not parse for proper OS. See #23
icon (optional) img The image shown to the left of the menu label
checked (optional) bool Should only be specified for checkbox or radio type menu items
submenu (optional) array : [MenuItems] Array of menu items. If submenu is specified, the type: 'submenu' can be omitted.
before (optional) string Inserts this item before the item with the specified id. If the referenced item doesn't exist the item will be inserted at the end of the menu
after (optional) string Inserts this item after the item with the specified id. If the referenced item doesn't exist the item will be inserted at the end of the menu

TODO

  • [x] ~~Change Menu Item states - checkmarks, radios~~
  • [x] ~~Add before, after, and id properties to menu item objects to order the menu item list~~
  • [x] ~~Add stacked menu bar style where the menu bar is placed below the titlebar~~
  • [ ] Change accelerator string to proper OS eg: CmdOrCtrl+Z should show ⌘Z on MacOS and Ctrl+Z on Windows #23
  • [ ] Scroll menu vertically when overflowing window height
  • [ ] Add a "more" menu item to the menu bar when the menu's items overflow the width of the menu bar
  • [ ] Add default role functions to be more in-line with Electron MenuItem Documentation
  • [ ] Instead of just hovering over to a submenu, add ability to lock a sub menu when parent menu is clicked on
  • [ ] All menus have fixed width to make it easier to calculate what side to render the submenu on. Menus should have dynamic width with a max-width property.
  • [ ] Add ability to change default icons with custom icons

Unsupported menu item properties

  • beforeGroupContaining and afterGroupContaining - order menu items based on implicit groups defined by separators
  • registerAccelerator - handle the registration of accelerators mapped to click functions

Try the example

# clone the repository
git clone https://github.com/Cristian006/frameless-titlebar.git
# move into the project directory
cd frameless-titlebar
# install module dependancies
yarn # or npm install
# move into example folder
cd ./example
# install example dependancies
yarn # or npm install
# to start the application run
yarn dev

Examples

Multi-Level Submenu Example / Submenu Header Labels

Default DarLinDefault

<TitleBar
  icon={defaultIcon}
  app="Electron Title Bar"
  menu={defaultTemplate}
/>

Stacked Menu Bar

DefaultStacked

<TitleBar
  icon={defaultIcon}
  app="Electron Title Bar"
  menu={defaultTemplate}
  theme={{
    menuStyle: 'stacked'
  }}
/>

GitHub - Dark Theme Example

Github DarGithub

<TitleBar
  icon={gitIcon}
  title="Project Name"
  menu={githubTemplate}
  theme={{
    barTheme: 'dark',
    barShowBorder: true,
    menuDimItems: false,
    showIconDarLin: false
  }}
/>

VSCode

VSCode DarCode

<TitleBar
  icon={codeIcon}
  app="Code"
  title="index.js - frameless-titlebar"
  menu={defaultTemplate}
  theme={{
    barTheme: 'dark',
    barBackgroundColor: 'rgb(36, 37, 38)',
    barColor: 'rgb(230, 230, 230)',
    menuHighlightColor: '#373277',
    menuDimItems: false,
    showIconDarLin: false
  }}
/>

Signal

Signal DarSignal

<TitleBar
  icon={signalIcon}
  app="Signal"
  menu={signalTemplate}
  theme={{
    barTheme: 'dark',
    barBackgroundColor: '#2090ea',
    menuHighlightColor: '#2090ea',
    barShowBorder: true,
    barBorderBottom: '1px solid #1a70b7',
    menuDimItems: false
  }}
/>

WhatsApp - Light Theme Example

WhatsApp DarWhatsApp

<TitleBar
  icon={whatIcon}
  app="WhatsApp"
  theme={{
    barTheme: 'light',
    barBackgroundColor: '#eaeaea',
    menuHighlightColor: '#33c151',
    menuDimItems: false
  }}
/>

Slack - Vertical Menu Example

Slack Slack

Leaving the dynamic project title in the app property is fine in this case since the toolbar menu has a vertical style where the menu items are to the left of the title

If you see the example for VSCode you'll see the app name can be set to "Code" (shortened title to the left of the menu items) and changing the title property will only be reflected on mac applications for the currently selected tab

<TitleBar
  icon={slackIcon}
  app="Slack - ElectronTitlebar"
  menu={slackTemplate}
  theme={{
    barTheme: 'dark',
    barBackgroundColor: '#251d24',
    menuStyle: 'vertical',
    menuHighlightColor: '#52a98c',
    menuDimItems: false
  }}
/>

Github Repository