{"id":16962232,"url":"https://github.com/6c65726f79/custom-titlebar","last_synced_at":"2025-03-22T14:30:54.249Z","repository":{"id":37797299,"uuid":"408170582","full_name":"6c65726f79/custom-titlebar","owner":"6c65726f79","description":"Poorly coded titlebar for Electron, NW.js and PWAs","archived":false,"fork":false,"pushed_at":"2023-03-06T17:07:17.000Z","size":1642,"stargazers_count":19,"open_issues_count":6,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-17T19:45:51.785Z","etag":null,"topics":["electron","macos","menubar","nwjs","pwa","titlebar","typescript","windows"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/@6c65726f79/custom-titlebar","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/6c65726f79.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-09-19T15:55:43.000Z","updated_at":"2025-01-18T21:55:49.000Z","dependencies_parsed_at":"2024-06-20T00:10:04.256Z","dependency_job_id":"88e1ea4a-22e4-479c-81dc-c529ac161fbd","html_url":"https://github.com/6c65726f79/custom-titlebar","commit_stats":{"total_commits":293,"total_committers":4,"mean_commits":73.25,"dds":"0.41638225255972694","last_synced_commit":"fdf21d1698d874f1295c1d17244f018d5e0c9ddc"},"previous_names":[],"tags_count":33,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/6c65726f79%2Fcustom-titlebar","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/6c65726f79%2Fcustom-titlebar/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/6c65726f79%2Fcustom-titlebar/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/6c65726f79%2Fcustom-titlebar/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/6c65726f79","download_url":"https://codeload.github.com/6c65726f79/custom-titlebar/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244971712,"owners_count":20540835,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["electron","macos","menubar","nwjs","pwa","titlebar","typescript","windows"],"created_at":"2024-10-13T23:05:46.095Z","updated_at":"2025-03-22T14:30:53.793Z","avatar_url":"https://github.com/6c65726f79.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# custom-titlebar\n\nPoorly coded titlebar for [Electron](https://www.electronjs.org/), [NW.js](https://nwjs.io/) and [PWAs](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps).\n\n![NPM](https://img.shields.io/npm/l/@6c65726f79/custom-titlebar) ![npm](https://img.shields.io/npm/v/@6c65726f79/custom-titlebar) ![npm bundle size](https://img.shields.io/bundlephobia/min/@6c65726f79/custom-titlebar) ![npm](https://img.shields.io/npm/dm/@6c65726f79/custom-titlebar) [![](https://data.jsdelivr.com/v1/package/npm/@6c65726f79/custom-titlebar/badge?style=rounded)](https://www.jsdelivr.com/package/npm/@6c65726f79/custom-titlebar)\n\n\n![Preview 1](screenshots/capture-1.png)\n\n\u003e Light/Dark skin\n\n![Preview 3](screenshots/capture-3.png)\n\n\u003e Control button styles\n\n\u003cdetails\u003e\n\u003csummary\u003eShow me more\u003c/summary\u003e\n\n![Preview 2](screenshots/capture-2.png)\n\n\u003e Condensed menu\n\n![Preview 4](https://raw.githubusercontent.com/6c65726f79/custom-titlebar/main/screenshots/capture-4.gif)\n\n\u003e Progressive web app\n\n\u003c/details\u003e\n\n# About\n\n**It's a library for Electron, NW.js and PWAs, it can be used on a basic website but it's useless ¯\\\\_(ツ)_/¯**\n\n## Main features\n\n* Compatible with any version of Electron 🎉\n* Works with Electron, NW.js and probably others 🤷‍♂️\n* Fully compatible with Progressive Web Apps and Window Controls Overlay 🔥\n* Works without any dependencies, so it won't break in the next major release of Electron 👀\n* Very small footprint (\u003c 30 kB) 👣\n* Options and methods very similar to [custom-electron-titlebar](https://www.npmjs.com/package/custom-electron-titlebar) 📖\n\n## Demo\n\nYou can see a demo of this library in a PWA here: https://6c65726f79.github.io/custom-titlebar/\n\nNotes:\n* Check the list of [compatible browsers](https://developer.mozilla.org/en-US/docs/Web/Manifest/display_override#browser_compatibility).\n* If the install button doesn't appear, try reloading and reopening the tab several times.\n* You may need to manually enable Window Controls Overlay until Chrome 98 is released: `chrome://flags/#enable-desktop-pwas-window-controls-overlay`\n\n## Inpiration\n\nThis package is highly inspired by [custom-electron-titlebar](https://www.npmjs.com/package/custom-electron-titlebar).\n\n## Motivations\n\nI needed a custom titlebar for Electron 14 to replace the unmaintained [custom-electron-titlebar](https://www.npmjs.com/package/custom-electron-titlebar), but I couldn't find any interesting ones, so I made it myself.\n\n## Not yet implemented\n\n* ~~MenuItem role, icon, radio~~ Done!\n* ~~Icons theme~~ Done!\n* Submenu scrollbar\n* Keyboard controls\n\n# Q\u0026A\n\n## Can I use this package without `@electron/remote`?\n\nAbsolutely! Check out the [advanced examples](https://github.com/6c65726f79/custom-titlebar/wiki/Advanced-examples#use-without-electronremote) to see how it's done.\n\n## How to fix Content Security Policy errors?\n\nSimply add `style-src 'unsafe-inline'` in the `Content-Security-Policy` meta tag.\n\n## How long before this package becomes unmaintained too?\n\nThis package doesn't rely on the Electron or NW.js API so it doesn't need as much maintenance as other packages. Even if I stop maintaining it and the API change dramatically, you could modify your code to match the new API. So theoretically this package can't become obsolete.\n\n# Install\n\n```\nnpm i @6c65726f79/custom-titlebar\n```\n\n# Usage\n\n## Node.js\n\n### JavaScript\n\n```javascript\nconst Titlebar = require('@6c65726f79/custom-titlebar');\n\nnew Titlebar({\n  backgroundColor: '#000'\n});\n```\n\n### TypeScript\n\n```typescript\nimport Titlebar from '@6c65726f79/custom-titlebar';\n\nnew Titlebar({\n  backgroundColor: '#000'\n});\n```\n\n## Browser\n\n```html\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/@6c65726f79/custom-titlebar/lib/index.js\"\u003e\u003c/script\u003e\n\n\u003cscript\u003e\n  new Titlebar({\n    backgroundColor: '#000'\n  });\n\u003c/script\u003e\n```\n\n# Examples\n\nSee the Wiki for more [advanced examples](https://github.com/6c65726f79/custom-titlebar/wiki/Advanced-examples).\n\n## Electron\n\n### main.js\n\n```javascript\nconst { initialize, enable } = require('@electron/remote/main');\nconst { app, BrowserWindow } = require('electron');\nconst path = require('path');\n\ninitialize();\n\nfunction createWindow () {\n  const win = new BrowserWindow({\n    width: 800,\n    height: 600,\n    frame: false,\n    webPreferences: {\n      contextIsolation: true,\n      preload: path.join(__dirname, 'preload.js')\n    }\n  })\n\n  enable(win.webContents);\n  \n  win.loadFile('index.html');\n}\n\napp.whenReady().then(() =\u003e {\n  createWindow();\n})\n```\n\n### preload.js\n\n```javascript\nconst { Menu, getCurrentWindow } = require('@electron/remote');\nconst Titlebar = require('@6c65726f79/custom-titlebar');\nconst { platform } = require('process');\n\nconst currentWindow = getCurrentWindow();\nlet titlebar;\n\ncurrentWindow.webContents.once('dom-ready', () =\u003e {\n  titlebar = new Titlebar({\n    menu: Menu.getApplicationMenu(),\n    backgroundColor: '#37474f',\n    platform: platform,\n    browserWindow: currentWindow, /* Only needed if you use MenuItem roles */\n    onMinimize: () =\u003e currentWindow.minimize(),\n    onMaximize: () =\u003e currentWindow.isMaximized() ? currentWindow.unmaximize() : currentWindow.maximize(),\n    onClose: () =\u003e currentWindow.close(),\n    isMaximized: () =\u003e currentWindow.isMaximized()\n  });\n});\n```\n\n## NW.js\n\n### package.json\n\n```json\n{\n  \"name\": \"helloworld\",\n  \"main\": \"index.html\",\n  \"window\": {\n    \"frame\": false,\n    \"toolbar\": false\n  },\n  \"dependencies\": {\n    \"@6c65726f79/custom-titlebar\": \"latest\"\n  }\n}\n```\n\n### index.html\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n  \u003chead\u003e\n    \u003ctitle\u003eHello World!\u003c/title\u003e\n    \u003cscript src=\"./node_modules/@6c65726f79/custom-titlebar/lib/index.js\"\u003e\u003c/script\u003e \n  \u003c/head\u003e\n  \u003cbody\u003e\n    \u003ch1\u003eHello World!\u003c/h1\u003e\n    \u003cscript\u003e\n      const gui = require('nw.gui');\n      const { platform } = require('process');\n      const win = gui.Window.get();\n      let maximized = false;\n\n      win.onMaximized.addListener(() =\u003e { maximized=true; });\n      win.onRestore.addListener(() =\u003e { maximized=false; });\n\n      const titlebar = new Titlebar({\n        backgroundColor: '#37474f',\n        platform: platform,\n        onMinimize: () =\u003e win.minimize(),\n        onMaximize: () =\u003e maximized ? win.restore() : win.maximize(),\n        onClose: () =\u003e win.close(),\n        isMaximized: () =\u003e maximized\n      });\n    \u003c/script\u003e\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\n## Progressive Web App\n\n### manifest.webmanifest\n\n```json\n{\n  \"background_color\": \"#2975ff\",\n  \"description\": \"Progressive Web Application with a custom titlebar\",\n  \"display\": \"standalone\",\n  \"display_override\": [\"window-controls-overlay\"],\n  \"icons\": [],\n  \"name\": \"Progressive Web Application\",\n  \"short_name\": \"custom-titlebar\",\n  \"start_url\": \"./\",\n  \"theme_color\": \"#2975ff\"\n}\n```\n\n### index.html\n\n```html\n\u003chtml\u003e\n    \u003chead\u003e\n        \u003ctitle\u003eTitlebar\u003c/title\u003e\n        \u003cscript src=\"https://cdn.jsdelivr.net/npm/@6c65726f79/custom-titlebar/lib/index.js\"\u003e\u003c/script\u003e\n        \u003clink rel=\"manifest\" href=\"manifest.webmanifest\"\u003e\n    \u003c/head\u003e\n    \u003cbody\u003e\n        \u003cdiv id=\"app\" style=\"padding:8px;\"\u003e\n            This is a web page\n        \u003c/div\u003e\n        \u003cscript\u003e\n          let titlebar;\n          const menu = [\n            {\n              label: 'File',\n              submenu: [\n                {\n                    label: 'Checkbox',\n                    type: 'checkbox',\n                    id: 'checkbox'\n                },\n                {\n                    label: 'Checked state',\n                    click: () =\u003e {\n                        alert(titlebar.getMenuItemById('checkbox')?.checked ? 'Checked' : 'Unchecked');\n                    }\n                }\n              ]\n            }\n          ];\n          \n          function createTitlebar() {\n            titlebar = new Titlebar({\n              backgroundUnfocusEffect: false,\n              windowControlsOverlay: true,\n              backgroundColor:\"#2975ff\",\n              menu\n            });\n          }\n\n          window.addEventListener('load', () =\u003e {\n            // Use the titlebar only in standalone mode\n            if (navigator.standalone || window.matchMedia('(display-mode: standalone)').matches) {\n              createTitlebar();\n            }\n\n            window.matchMedia('(display-mode: standalone)').onchange = (e) =\u003e {\n              e.matches ? createTitlebar() : titlebar.dispose();\n            }\n          });\n        \u003c/script\u003e\n    \u003c/body\u003e\n\u003c/html\u003e\n```\n\n# Options\n\nAll parameters are optional.\n\n| Parameter                | Type       | Description                                                                        | Default          |\n| ------------------------ | ---------- | ---------------------------------------------------------------------------------- | ---------------- |\n| backgroundColor          | `string`   | The background color of the titlebar. The value must be a valid CSS color.         | `\"#FFFFFF\"`      |\n| backgroundUnfocusEffect  | `boolean`  | Enables or disables the unfocus effect on the background of the titlebar.          | `true`           |\n| browserWindow            | `object`   | The current `BrowserWindow`. **(Electron only)**                                   | undefined        |\n| condensed                | `boolean`  | Force the menu bar to be condensed.                                                | `false`          |\n| closeable                | `boolean`  | Enables or disables the close button.                                              | `true`           |\n| drag                     | `boolean`  | Define whether or not you can drag the window.                                     | `true`           |\n| hideControlsOnDarwin     | `boolean`  | Set this option to true if you're using `titleBarStyle: 'hidden'` on macOS. **(Electron only)** | `false`          |\n| hideMenuOnDarwin         | `boolean`  | Hide the menu bar when the `platform` is `darwin`.                                 | `true`           |\n| height                   | `number`   | The height of the titlebar.                                                        | `30`             |\n| icon                     | `string`   | The icon of the titlebar.                                                          | undefined        |\n| isMaximized              | `function` | A function that return `true` or `false` if the window is maximized or not.        | undefined        |\n| maximizable              | `boolean`  | Enables or disables the maximize button.                                           | `true`           |\n| menu                     | `object`   | List of MenuItem to show in the menu bar. ([Electron](https://www.electronjs.org/docs/api/menu-item) or [NW.js](https://docs.nwjs.io/en/latest/References/MenuItem/)) | undefined        | \n| menuItemClickHandler     | `function` | A function that takes a `commandId` as parameter to handle menu item clicks.       | undefined        |\n| minimizable              | `boolean`  | Enables or disables the minimize button.                                           | `true`           |\n| onClose                  | `function` | The function to call when the close button is clicked.                             | undefined        |\n| onMaximize               | `function` | The function to call when the maximize/restore button is clicked.                  | undefined        |\n| onMinimize               | `function` | The function to call when the minimize button is clicked.                          | undefined        |\n| overflow                 | `string`   | The overflow of the container. (`auto`, `visible`, `hidden`)                       | `\"auto\"`         |\n| platform                 | `string`   | Style of the control buttons. (`win`, `darwin`)                                    | `\"win\"`          |\n| title                    | `string`   | Window title.                                                                      | `document.title` |\n| titleHorizontalAlignment | `string`   | Set horizontal alignment of the window title. (`left`, `center`, `right`)          | `\"center\"`       |\n| unfocusEffect            | `boolean`  | Enables or disables the unfocus effect on the text and background of the titlebar. | `true`           |\n| windowControlsOverlay    | `boolean`  | Set this option to true if you're using [Window Controls Overlay](https://github.com/WICG/window-controls-overlay/blob/main/explainer.md). | `false`          |\n\n# Methods\n\n## getMenuItemById\n\nReturns the MenuItem with the specified `id`.\n\n```javascript\nconst titlebar = new Titlebar({\n  menu: [{label: 'Item 1', id: 'item1'}]\n});\n\nconst menuItem = titlebar.getMenuItemById('item1');\n\nconsole.log(menuItem.label); // Item 1\n```\n\n## updateOptions\n\nThis method updates all parameters that are specified.\n\n```javascript\ntitlebar.updateOptions({\n  menu: Menu.getApplicationMenu(),\n  condensed: 'true',\n  titleHorizontalAlignment: 'left'\n});\n```\n\n## updateTitle\n\nThis method update the title of the titlebar. If you change the content of the title tag, you should call this method to update the title.\n\n```javascript\ndocument.title = 'My new title';\ntitlebar.updateTitle();\n\n// Or you can do as follows and avoid writing document.title\ntitlebar.updateTitle('New Title');\n```\n\n## updateMenu\n\n\u003e Deprecated: This method will be removed in v1.0.0, use `updateOptions` instead.\n\nThis method updates or creates the menu. You can use an array of MenuItem from [Electron](https://www.electronjs.org/docs/api/menu-item)/[NW.js](https://docs.nwjs.io/en/latest/References/MenuItem/), or directly `Menu.getApplicationMenu()` in Electron.\n\n```javascript\n// With a menu template\nconst menu = [\n  {\n    label: 'Item 1',\n    submenu: [\n      {\n        label: 'Subitem 1',\n        click: () =\u003e console.log('Clicked on subitem 1')\n      },\n      {\n        type: 'separator'\n      },\n      {\n        label: 'Subitem 2',\n        click: () =\u003e console.log('Clicked on subitem 2')\n      },\n    ]\n  },\n  {\n    label: 'Item 2',\n    submenu: [\n      {\n        label: 'Subitem checkbox',\n        type: 'checkbox',\n        checked: true\n      },\n      {\n        type: 'separator'\n      },\n      {\n        label: 'Subitem with submenu',\n        submenu: [\n          {\n            label: 'Submenu item 1',\n            accelerator: 'Ctrl+T'\n          }\n        ]\n      }\n    ]\n  }\n];\ntitlebar.updateMenu(menu);\n\n// Or with getApplicationMenu in Electron\ntitlebar.updateMenu(Menu.getApplicationMenu());\n\n// Disable menu\ntitlebar.updateMenu();\n```\n\n## dispose\n\nThis method removes the titlebar completely and all recorded events.\n\n```javascript\ntitlebar.dispose();\n```\n\n# CSS Classes\n\nThe following CSS classes exist and can be used to customize the titlebar.\n\n| Class name                     | Description                                    |\n| ------------------------------ | ---------------------------------------------- |\n| `custom-titlebar`              | Style of the titlebar.                         |\n| `custom-titlebar-appicon`      | Style of the icon.                             |\n| `custom-titlebar-container`    | Style of the container under the titlebar.     |\n| `custom-titlebar-controls`     | Style of the window controls.                  |\n| `custom-titlebar-menu-item`    | Style of the main menu items.                  |\n| `custom-titlebar-separator`    | Style of the separators.                       |\n| `custom-titlebar-submenu`      | Style of the submenus.                         |\n| `custom-titlebar-submenu-item` | Style of the submenu items.                    |\n\n----\n\nMade with love and fun from France ❤\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F6c65726f79%2Fcustom-titlebar","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F6c65726f79%2Fcustom-titlebar","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F6c65726f79%2Fcustom-titlebar/lists"}