diff --git a/README.md b/README.md index 8a93300..59c155c 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,8 @@ You can pass an optional options object into the `menubar({ ... })` function: - `showOnAllWorkspaces` (default true) - Makes the window available on all OS X workspaces. - `windowPosition` (default trayCenter and trayBottomCenter on Windows) - Sets the window position (x and y will still override this), check [positioner docs](https://github.com/jenslind/electron-positioner#docs) for valid values. - `showDockIcon` (default false) - Configure the visibility of the application dock icon. -- `showOnRightClick` (default false) - Show the window on 'right-click' event instead of regular 'click' +- `trigger` (default `'click'`) - Tray event that toggles the menubar window. One of `'click'`, `'right-click'`, or `'none'`. Use `'none'` to disable automatic toggling — useful when a single tray icon serves multiple windows. The window can still be shown by calling `mb.showWindow()` directly. +- `showOnRightClick` (default false) - **Deprecated**, use `trigger: 'right-click'` instead. Show the window on 'right-click' event instead of regular 'click'. See the reference [API docs](./docs/interfaces/_types_.options.md). diff --git a/src/Menubar.spec.ts b/src/Menubar.spec.ts index be13a58..d32c214 100644 --- a/src/Menubar.spec.ts +++ b/src/Menubar.spec.ts @@ -101,3 +101,75 @@ describe('Menubar', () => { }); }); }); + +describe('Menubar trigger option', () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + const trayEvents = (mb: Menubar): string[] => + (mb.tray.on as Mock).mock.calls.map(([event]) => event as string); + + const onReady = (mb: Menubar, assertions: () => void): Promise => + new Promise((resolve) => { + mb.on('ready', () => { + assertions(); + resolve(); + }); + }); + + it('defaults to binding `click` and `double-click`', () => { + const mb = new Menubar(app, { preloadWindow: true }); + return onReady(mb, () => { + expect(trayEvents(mb)).toEqual( + expect.arrayContaining(['click', 'double-click']), + ); + expect(trayEvents(mb)).not.toContain('right-click'); + }); + }); + + it('binds `right-click` when `trigger: "right-click"`', () => { + const mb = new Menubar(app, { + preloadWindow: true, + trigger: 'right-click', + }); + return onReady(mb, () => { + expect(trayEvents(mb)).toEqual( + expect.arrayContaining(['right-click', 'double-click']), + ); + expect(trayEvents(mb)).not.toContain('click'); + }); + }); + + it('binds nothing when `trigger: "none"`', () => { + const mb = new Menubar(app, { preloadWindow: true, trigger: 'none' }); + return onReady(mb, () => { + expect(trayEvents(mb)).not.toContain('click'); + expect(trayEvents(mb)).not.toContain('right-click'); + expect(trayEvents(mb)).not.toContain('double-click'); + }); + }); + + it('falls back to `showOnRightClick` when `trigger` is unset', () => { + const mb = new Menubar(app, { + preloadWindow: true, + showOnRightClick: true, + }); + return onReady(mb, () => { + expect(trayEvents(mb)).toContain('right-click'); + expect(trayEvents(mb)).not.toContain('click'); + }); + }); + + it('lets `trigger` win over the deprecated `showOnRightClick`', () => { + const mb = new Menubar(app, { + preloadWindow: true, + showOnRightClick: true, + trigger: 'click', + }); + return onReady(mb, () => { + expect(trayEvents(mb)).toContain('click'); + expect(trayEvents(mb)).not.toContain('right-click'); + }); + }); +}); diff --git a/src/Menubar.ts b/src/Menubar.ts index b97edc2..7a1709f 100644 --- a/src/Menubar.ts +++ b/src/Menubar.ts @@ -246,17 +246,19 @@ export class Menubar extends EventEmitter { trayImage = path.join(__dirname, '..', 'assets', 'IconTemplate.png'); // Default cat icon } - const defaultClickEvent = this._options.showOnRightClick - ? 'right-click' - : 'click'; + const trigger = + this._options.trigger ?? + (this._options.showOnRightClick ? 'right-click' : 'click'); this._tray = this._options.tray || new Tray(trayImage); // Type guards for TS not to complain if (!this.tray) { throw new Error('Tray has been initialized above'); } - this.tray.on(defaultClickEvent as Parameters[0], this.clicked); - this.tray.on('double-click', this.clicked); + if (trigger !== 'none') { + this.tray.on(trigger as Parameters[0], this.clicked); + this.tray.on('double-click', this.clicked); + } this.tray.setToolTip(this._options.tooltip); if (!this._options.windowPosition) { diff --git a/src/types.ts b/src/types.ts index cf37f65..2aa692f 100644 --- a/src/types.ts +++ b/src/types.ts @@ -71,8 +71,19 @@ export interface Options { showOnAllWorkspaces?: boolean; /** * Show the window on 'right-click' event instead of regular 'click'. + * @deprecated Use {@link Options.trigger} instead. Will be removed in the + * next major release. */ showOnRightClick?: boolean; + /** + * Tray event that toggles the menubar window. Set to `'none'` to disable + * automatic toggling — the window can still be shown by calling + * {@link Menubar.showWindow} directly. Useful when a single tray icon serves + * multiple windows. + * @default `'click'` (or `'right-click'` if the deprecated + * {@link Options.showOnRightClick} is `true`) + */ + trigger?: 'click' | 'right-click' | 'none'; /** * Menubar tray icon tooltip text. Calls [`tray.setTooltip`](https://electronjs.org/docs/api/tray#traysettooltiptooltip). */