Skip to content

Tray

Create trays in the main process. Images may be absolute paths or bundled views:// URLs.

import { Tray } from "electrobun/main";
const tray = new Tray({
title: "My app",
image: "views://assets/tray-icon.png",
template: true,
width: 32,
height: 32,
});
const menuState: Record<string, boolean> = {
notifications: true,
};
function updateTrayMenu() {
tray.setMenu([
{
type: "normal",
label: "Notifications",
action: "notifications",
checked: menuState.notifications,
},
{ type: "separator" },
{
type: "normal",
label: "Quit",
action: "quit",
},
]);
}
// Install the menu before listening for interaction. This is required for the
// supported Linux AppIndicator interaction path and works on every platform.
updateTrayMenu();
type TrayClickEvent = {
data: { id: number; action: string; data?: unknown };
};
tray.on("tray-clicked", (event: unknown) => {
const { action } = (event as TrayClickEvent).data;
if (action === "notifications") {
menuState.notifications = !menuState.notifications;
updateTrayMenu();
}
});

Constructor options

OptionTypeDefaultPurpose
titlestring""Text shown by the tray backend.
imagestring""views:// URL or absolute image path.
templatebooleantrueTreat the image as a macOS template image.
widthnumber16Requested image width.
heightnumber16Requested image height.

Methods and lookup

import { Tray } from "electrobun/main";
const tray = new Tray({
title: "Status",
image: "views://assets/tray-icon.png",
});
tray.setTitle("Ready");
tray.setImage("views://assets/tray-ready.png");
tray.setVisible(false);
tray.setVisible(true);
const bounds = tray.getBounds();
const sameTray = Tray.getById(tray.id);
const allTrays = Tray.getAll();
void bounds;
void sameTray;
void allTrays;
tray.remove();

Use Tray.removeById(id) instead when only a stored tray ID is available.

setMenu() replaces the current menu. Tray menu normal items require type: "normal" and label; they also support action, data, submenu, enabled, checked, hidden, and tooltip.

Platform behavior

Ayatana AppIndicator backend supports tray menus and their actions but does not expose raw primary icon activation. Linux apps should use setMenu() and handle menu actions; do not wait for an icon-only click to install the menu. A backend that exposes raw activation may emit tray-clicked with an empty action; portable apps should use explicit menu actions.