> ## Documentation Index
> Fetch the complete documentation index at: https://webview.js.org/llms.txt
> Use this file to discover all available pages before exploring further.

# System Tray Guide

> Learn how to keep your application running in the system tray, create context menus, and respond to tray events.

System tray icons let your application continue running without requiring a visible window. They are commonly used for messaging apps, clipboard managers, music players, background services, and utilities.

Unlike creating a window directly, tray icons must be created through `app.createTrayIcon()`, which ensures they are initialized on the native event loop.

## Before you begin

Tray icons should be created after the application is ready.

```js theme={null}
import { Application } from '@webviewjs/webview';

const app = new Application();

app.whenReady().then(() => {
  // Create tray icon here
});

app.run();
```

## Creating your first tray icon

The example below creates a tray icon with two menu items.

```js theme={null}
import { Application } from '@webviewjs/webview';

const app = new Application();

const win = app.createBrowserWindow({
  title: 'Tray Example',
});

win.createWebview({
  html: '<h1>Hello!</h1>',
});

const size = 16;
const rgba = Buffer.alloc(size * size * 4);

for (let i = 0; i < rgba.length; i += 4) {
  rgba[i] = 70;
  rgba[i + 1] = 150;
  rgba[i + 2] = 240;
  rgba[i + 3] = 255;
}

let tray;

app.whenReady().then(() => {
  tray = app.createTrayIcon({
    icon: {
      data: rgba,
      width: size,
      height: size,
    },
    tooltip: 'My Application',
    menu: {
      items: [
        {
          id: 'show',
          label: 'Show window',
        },
        {
          role: 'separator',
        },
        {
          id: 'quit',
          label: 'Quit',
        },
      ],
    },
  });
});

app.on('custom-menu-click', ({ customMenuEvent }) => {
  switch (customMenuEvent.id) {
    case 'show':
      win.show();
      break;

    case 'quit':
      app.exit();
      break;
  }
});

app.run();
```

After launching, your application will appear in the operating system's notification area with a context menu.

## Showing and hiding the window

Many tray applications hide instead of closing.

```js theme={null}
tray.on('click', () => {
  if (win.isVisible()) {
    win.hide();
  } else {
    win.show();
    win.focus();
  }
});
```

This produces the familiar behavior used by applications like Discord, Slack, and Spotify.

## Updating the tray icon

You can replace the icon at runtime.

```js theme={null}
tray.setIcon(buffer);
```

Or provide raw RGBA pixels.

```js theme={null}
tray.setIcon(rgba, width, height);
```

This is useful for:

* unread notifications
* connection status
* syncing indicators
* recording state

## Updating the tooltip

```js theme={null}
tray.setTooltip('Downloading updates...');
```

Changing the tooltip is an easy way to communicate application state without opening a window.

## Replacing the menu

Menus are not fixed after creation.

```js theme={null}
tray.setMenu({
  items: [
    {
      id: 'pause',
      label: 'Pause',
    },
    {
      id: 'quit',
      label: 'Quit',
    },
  ],
});
```

This allows menus to reflect the application's current state.

## Responding to clicks

Tray icons emit pointer events.

```js theme={null}
tray.on('click', (event) => {
  console.log(event.button);
});

tray.on('double-click', () => {
  win.show();
});

tray.on('enter', () => {
  console.log('Mouse entered');
});

tray.on('leave', () => {
  console.log('Mouse left');
});
```

Menu selections are handled separately through the application's `custom-menu-click` event.

```js theme={null}
app.on('custom-menu-click', ({ customMenuEvent }) => {
  console.log(customMenuEvent.id);
});
```

## Temporarily hiding the tray icon

Hide the icon without destroying it.

```js theme={null}
tray.setVisible(false);

// ...

tray.setVisible(true);
```

All menu items and event listeners remain intact.

## Removing the tray icon

To remove the icon permanently:

```js theme={null}
tray.dispose();
```

Calling `app.exit()` automatically disposes every tray icon owned by the application.

## Platform differences

Some tray features are platform specific.

| Feature        | Windows | macOS | Linux |
| -------------- | ------- | ----- | ----- |
| Tooltip        | ✓       | ✓     | ✗     |
| Menu bar title | ✗       | ✓     | ✗     |
| Template icons | ✗       | ✓     | ✗     |
| Pointer events | ✓       | ✓     | ✗     |

## Next steps

The guide covers the most common workflows. For the complete API, available methods, events, and configuration options, see the **TrayIcon API Reference**.
