Skip to content

Native Features: Menus, Trays, and Dialogs

Native Features: Menus, Trays, and Dialogs

Section titled “Native Features: Menus, Trays, and Dialogs”

One of the main reasons to use Tauri over a standard web app is the ability to integrate deeply with the Operating System. In this chapter, we will implement features that give your app that “native feel”: Application Menus, System Trays, and Native File Dialogs.

The Application Menu appears at the top of the screen on macOS or at the top of the window on Windows and Linux. It provides standard actions like “File,” “Edit,” and “View.”

In Tauri v2, you typically construct menus in Rust within your lib.rs file. You can create a default menu or build a custom one item by item.

src-tauri/src/lib.rs
use tauri::menu::{Menu, MenuItem};
pub fn run() {
tauri::Builder::default()
.setup(|app| {
// Create a custom menu
let file_menu = Menu::new(app)?;
file_menu.append(&MenuItem::with_id(app, "quit", "Quit", true, None::<&str>)?)?;
app.set_menu(file_menu)?;
Ok(())
})
.run(tauri::generate_context!())
.expect("error while running tauri application");
}

The System Tray (or Notification Area) allows your app to persist in the background even when the main window is closed. This is perfect for music players, chat apps, or utility tools.

To add a tray, you configure it in Rust using TrayIconBuilder. You can attach a menu to it, allowing users to right-click the icon and select options like “Show” or “Exit.”

src-tauri/src/lib.rs
use tauri::tray::TrayIconBuilder;
// Inside your builder chain
.setup(|app| {
TrayIconBuilder::new()
.icon(app.default_window_icon().unwrap().clone())
.tooltip("My Tauri App")
.on_menu_event(|app, event| {
// Handle click events here
})
.build(app)?;
Ok(())
})

Web browsers use <input type="file">, which is functional but limited. Tauri allows you to open the OS’s native file pickers for opening and saving files. This provides a familiar experience for users and allows access to the file path, not just the file buffer.

We use the official dialog plugin for this. First, ensure you have installed the plugin (@tauri-apps/plugin-dialog) and registered it in Rust.

import { open, save } from '@tauri-apps/plugin-dialog';
// Open a file selection dialog
const selected = await open({
multiple: false,
filters: [{
name: 'Images',
extensions: ['png', 'jpeg']
}]
});
// Save a file dialog
const filePath = await save({
filters: [{
name: 'Text',
extensions: ['txt']
}]
});

These native integrations bridge the gap between a web page and a true desktop application.