Saltar al contenido

Menú de Ventana

Los menús de aplicación nativos se pueden adjuntar tanto a una ventana como a la bandeja del sistema (system tray). Disponible en escritorio.

Para crear un menú de ventana nativo de nivel base y adjuntarlo a una ventana. Puedes crear varios tipos de elementos de menú, incluidos elementos básicos, elementos con casilla de verificación (check items) y separadores:

Usa la función estática Menu.new para crear un menú de ventana:

import { Menu } from '@tauri-apps/api/menu';
const menu = await Menu.new({
items: [
{
id: 'quit',
text: 'Quit',
action: () => {
console.log('quit pressed');
},
},
{
id: 'check_item',
text: 'Check Item',
checked: true,
},
{
item: 'Separator',
},
{
id: 'disabled_item',
text: 'Disabled Item',
enabled: false,
},
{
id: 'status',
text: 'Status: Processing...',
},
],
});
// If a window was not created with an explicit menu or had one set explicitly,
// this menu will be assigned to it.
menu.setAsAppMenu().then(async (res) => {
console.log('menu set success', res);
// Update individual menu item text
const statusItem = await menu.get('status');
if (statusItem) {
await statusItem.setText('Status: Ready');
}
});

Escuchar eventos en elementos de menú personalizados

Sección titulada “Escuchar eventos en elementos de menú personalizados”

Cada elemento de menú personalizado activa un evento al hacer clic. Usa la API on_menu_event para manejarlos.

import { Menu } from '@tauri-apps/api/menu';
const menu = await Menu.new({
items: [
{
id: 'Open',
text: 'open',
action: () => {
console.log('open pressed');
},
},
{
id: 'Close',
text: 'close',
action: () => {
console.log('close pressed');
},
},
],
});
await menu.setAsAppMenu();

Los menús multinivel te permiten agrupar elementos de menú en categorías como “Archivo”, “Edición”, etc. Estos aparecerán como parte de la ventana de la aplicación en Windows o Linux, o en la barra de menú en macOS.

Nota: Al usar submenús en macOS, todos los elementos deben estar agrupados bajo un submenú. Los elementos de nivel superior serán ignorados. Además, el primer submenú se colocará bajo el menú "Acerca de" de la aplicación de forma predeterminada, independientemente de la etiqueta de texto text. Deberías incluir un submenú como la primera entrada (por ejemplo, un submenú “Acerca de”) para ocupar este espacio.

import { Menu, MenuItem, Submenu } from '@tauri-apps/api/menu';
// Will become the application submenu on MacOS
const aboutSubmenu = await Submenu.new({
text: 'About',
items: [
await MenuItem.new({
id: 'quit',
text: 'Quit',
action: () => {
console.log('Quit pressed');
},
}),
],
});
const fileSubmenu = await Submenu.new({
text: 'File',
icon: 'folder', // Optional: Add an icon to the submenu
items: [
await MenuItem.new({
id: 'new',
text: 'New',
action: () => {
console.log('New clicked');
},
}),
await MenuItem.new({
id: 'open',
text: 'Open',
action: () => {
console.log('Open clicked');
},
}),
await MenuItem.new({
id: 'save_as',
text: 'Save As...',
action: () => {
console.log('Save As clicked');
},
}),
],
});
const editSubmenu = await Submenu.new({
text: 'Edit',
items: [
await MenuItem.new({
id: 'undo',
text: 'Undo',
action: () => {
console.log('Undo clicked');
},
}),
await MenuItem.new({
id: 'redo',
text: 'Redo',
action: () => {
console.log('Redo clicked');
},
}),
],
});
const menu = await Menu.new({
items: [aboutSubmenu, fileSubmenu, editSubmenu],
});
menu.setAsAppMenu();
// You can also update the submenu icon dynamically
fileSubmenu.setIcon('document');
// Or set a native icon (only one type applies per platform)
fileSubmenu.setNativeIcon('NSFolder');

Para usar elementos de menú integrados (nativos) que tienen un comportamiento predefinido por el sistema operativo o Tauri:

import { Menu, PredefinedMenuItem } from '@tauri-apps/api/menu';
const copy = await PredefinedMenuItem.new({
text: 'copy-text',
item: 'Copy',
});
const separator = await PredefinedMenuItem.new({
text: 'separator-text',
item: 'Separator',
});
const undo = await PredefinedMenuItem.new({
text: 'undo-text',
item: 'Undo',
});
const redo = await PredefinedMenuItem.new({
text: 'redo-text',
item: 'Redo',
});
const cut = await PredefinedMenuItem.new({
text: 'cut-text',
item: 'Cut',
});
const paste = await PredefinedMenuItem.new({
text: 'paste-text',
item: 'Paste',
});
const select_all = await PredefinedMenuItem.new({
text: 'select_all-text',
item: 'SelectAll',
});
const menu = await Menu.new({
items: [copy, separator, undo, redo, cut, paste, select_all],
});
await menu.setAsAppMenu();

Si quieres cambiar el estado del menú, como el texto, icono o el estado de verificación, puedes usar set_menu nuevamente:

import {
Menu,
CheckMenuItem,
IconMenuItem,
MenuItem,
} from '@tauri-apps/api/menu';
import { Image } from '@tauri-apps/api/image';
let currentLanguage = 'en';
const check_sub_item_en = await CheckMenuItem.new({
id: 'en',
text: 'English',
checked: currentLanguage === 'en',
action: () => {
currentLanguage = 'en';
check_sub_item_en.setChecked(currentLanguage === 'en');
check_sub_item_zh.setChecked(currentLanguage === 'cn');
console.log('English pressed');
},
});
const check_sub_item_zh = await CheckMenuItem.new({
id: 'zh',
text: 'Chinese',
checked: currentLanguage === 'zh',
action: () => {
currentLanguage = 'zh';
check_sub_item_en.setChecked(currentLanguage === 'en');
check_sub_item_zh.setChecked(currentLanguage === 'zh');
check_sub_item_zh.setAccelerator('Ctrl+L');
console.log('Chinese pressed');
},
});
// Load icon from path
const icon = await Image.fromPath('../src/icon.png');
const icon2 = await Image.fromPath('../src/icon-2.png');
const icon_item = await IconMenuItem.new({
id: 'icon_item',
text: 'Icon Item',
icon: icon,
action: () => {
icon_item.setIcon(icon2);
console.log('icon pressed');
},
});
const text_item = await MenuItem.new({
id: 'text_item',
text: 'Text Item',
action: () => {
text_item.setText('Text Item Changed');
console.log('text pressed');
},
});
const menu = await Menu.new({
items: [
{
id: 'change menu',
text: 'change_menu',
items: [text_item, check_sub_item_en, check_sub_item_zh, icon_item],
},
],
});
await menu.setAsAppMenu();

© 2026 Colaboradores de Tauri. CC-BY / MIT