tray WINMACLNX
Create system tray icons with native context menus. Tray icons persist even when the window is minimized or closed (when configured to run in the background).
Capability
{ "capabilities": { "tray": true } }Usage
import { tray } from '@glyx-dev/react'tray.create(rgba, width, height, tooltip, menu?)
Create a tray icon from raw RGBA pixel data.
const id = tray.create(
iconBytes, // ArrayBuffer of RGBA pixels (4 bytes per pixel)
32, // icon width in pixels
32, // icon height in pixels
'My App', // tooltip text
[ // optional menu items
{ id: 'show', label: 'Show Window' },
{ id: '', separator: true },
{ id: 'quit', label: 'Quit' },
]
);Returns number — a tray handle ID, or 0 on failure.
Menu items:
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier (used in events). Set to '' for separators. |
label | string | Display text |
enabled | boolean | Default true. false grays out the item. |
checked | boolean | Default false. Shows a checkmark. |
separator | boolean | Render a horizontal separator line. |
accelerator | string | Keyboard shortcut hint (e.g. 'Cmd+Q'). Platform-dependent. |
children | TrayMenuItem[] | Nested submenu items. |
tray.destroy(id)
Remove a tray icon.
tray.destroy(id);Returns boolean — true if the icon existed and was removed.
tray.updateMenu(id, menu)
Replace the context menu for an existing tray icon.
tray.updateMenu(id, [
{ id: 'play', label: playing ? 'Pause' : 'Play' },
{ id: 'next', label: 'Next Track' },
{ id: 'prev', label: 'Previous Track' },
]);Returns boolean — true on success.
tray.setTooltip(id, tooltip)
Update the tooltip shown when hovering over the icon.
tray.setTooltip(id, 'Now Playing: Song Title');tray.pollEvents()
Poll for pending tray events. Call each frame (from a setInterval or requestAnimationFrame) to process user interactions.
const raw = tray.pollEvents();
if (!raw) return;
const events = JSON.parse(raw);
for (const ev of events) {
if (ev.MenuItemClick?.item_id === 'quit') {
tray.destroy(id);
window.quit();
}
if (ev.DoubleClick) {
window.show();
}
}Returns string — a JSON array of TrayEvent objects, or an empty string if no events are pending.
Event types:
type TrayEvent =
| { Click: { tray_id: number } }
| { DoubleClick: { tray_id: number } }
| { MenuItemClick: { tray_id: number; item_id: string } }Example: Media Player Tray
See the full Media Player example which uses tray icons with transport controls (Play/Pause, Next, Previous, Quit).
import { tray } from '@glyx-dev/react'
function useTray(playing, onPlay, onNext, onPrev) {
const trayRef = useRef(0);
useEffect(() => {
const id = tray.create(icon, 16, 16, 'Media Player', [
{ id: 'play', label: playing ? 'Pause' : 'Play' },
{ id: 'next', label: 'Next' },
{ id: 'prev', label: 'Previous' },
{ id: '', separator: true },
{ id: 'quit', label: 'Quit' },
]);
if (id) trayRef.current = id;
const iv = setInterval(() => {
const raw = tray.pollEvents();
if (!raw) return;
for (const ev of JSON.parse(raw)) {
if (ev.MenuItemClick?.item_id === 'play') onPlay();
if (ev.MenuItemClick?.item_id === 'next') onNext();
if (ev.MenuItemClick?.item_id === 'prev') onPrev();
if (ev.MenuItemClick?.item_id === 'quit') { tray.destroy(id); window.quit(); }
}
}, 500);
return () => { clearInterval(iv); tray.destroy(trayRef.current); };
}, []);
}Platform Notes
| Platform | Details |
|---|---|
| Windows | Tray icons appear in the system notification area. An HWND is required (the main window provides this automatically). |
| macOS | Tray icons appear in the menu bar. The app must be running on the main thread (Glyx handles this). |
| Linux | Requires libayatana-appindicator3-1 (or libappindicator3-1) installed. On modern GNOME, you may need the AppIndicator extension (opens in a new tab). |