Menu API
Dieser Inhalt ist noch nicht in deiner Sprache verfügbar.
Overview
Section titled “Overview”The Menu API provides methods to create and manage application menus, context menus, and system tray menus.
Menu Types:
- Application Menus - Top menu bar (File, Edit, etc.)
- Context Menus - Right-click menus
- System Tray Menus - Menus in the system tray/notification area
Creating Menus
Section titled “Creating Menus”NewMenu()
Section titled “NewMenu()”Creates a new menu.
func (a *App) NewMenu() *MenuExample:
menu := app.NewMenu()Menu Methods
Section titled “Menu Methods”Adds a menu item to the menu.
func (m *Menu) Add(label string) *MenuItemParameters:
label- The text displayed for the menu item
Returns: The created menu item
Example:
item := menu.Add("Open File")item.OnClick(func(ctx *application.Context) { // Handle click})AddSubmenu()
Section titled “AddSubmenu()”Adds a submenu to the menu.
func (m *Menu) AddSubmenu(label string) *MenuParameters:
label- The submenu label
Returns: The created submenu
Example:
fileMenu := menu.AddSubmenu("File")fileMenu.Add("New")fileMenu.Add("Open")fileMenu.Add("Save")AddSeparator()
Section titled “AddSeparator()”Adds a visual separator line between menu items.
func (m *Menu) AddSeparator()Example:
menu.Add("Copy")menu.Add("Paste")menu.AddSeparator()menu.Add("Select All")Best practice: Use separators to group related menu items.
AddCheckbox()
Section titled “AddCheckbox()”Adds a checkable menu item.
func (m *Menu) AddCheckbox(label string, checked bool) *MenuItemParameters:
label- The checkbox labelchecked- Initial checked state
Example:
darkMode := menu.AddCheckbox("Dark Mode", false)darkMode.OnClick(func(ctx *application.Context) { isChecked := darkMode.Checked() // Toggle dark mode})AddRadio()
Section titled “AddRadio()”Adds a radio menu item (mutually exclusive group).
func (m *Menu) AddRadio(label string, checked bool) *MenuItemParameters:
label- The radio button labelchecked- Initial checked state
Example:
// Create radio group for view modesviewMenu := menu.AddSubmenu("View")listView := viewMenu.AddRadio("List View", true)gridView := viewMenu.AddRadio("Grid View", false)treeView := viewMenu.AddRadio("Tree View", false)
listView.OnClick(func(ctx *application.Context) { setViewMode("list")})gridView.OnClick(func(ctx *application.Context) { setViewMode("grid")})Update()
Section titled “Update()”Updates the menu to reflect any changes made to menu items.
func (m *Menu) Update()Example:
item.SetEnabled(false)menu.Update() // Must call to apply changesImportant: Always call Update() after modifying menu item properties.
Menu Item Methods
Section titled “Menu Item Methods”OnClick()
Section titled “OnClick()”Registers a click handler for the menu item.
func (mi *MenuItem) OnClick(callback func(ctx *application.Context)) *MenuItemParameters:
callback- Function called when item is clicked
Returns: The menu item (for chaining)
Example:
item.OnClick(func(ctx *application.Context) { fmt.Println("Menu item clicked") app.Logger.Info("User clicked menu item")})SetLabel()
Section titled “SetLabel()”Changes the menu item’s label.
func (mi *MenuItem) SetLabel(label string) *MenuItemExample:
item.SetLabel("Save As...")menu.Update()SetEnabled()
Section titled “SetEnabled()”Enables or disables the menu item.
func (mi *MenuItem) SetEnabled(enabled bool) *MenuItemExample:
// Disable save when no document is opensaveItem.SetEnabled(hasOpenDocument)menu.Update()Common pattern:
// Update menu state based on application statefunc updateMenuState() { saveItem.SetEnabled(hasUnsavedChanges) undoItem.SetEnabled(canUndo) redoItem.SetEnabled(canRedo) menu.Update()}SetChecked()
Section titled “SetChecked()”Sets the checked state for checkbox/radio menu items.
func (mi *MenuItem) SetChecked(checked bool) *MenuItemExample:
darkModeItem.SetChecked(isDarkModeEnabled)menu.Update()Checked()
Section titled “Checked()”Returns the current checked state.
func (mi *MenuItem) Checked() boolExample:
if darkModeItem.Checked() { // Dark mode is enabled}SetAccelerator()
Section titled “SetAccelerator()”Sets a keyboard shortcut for the menu item.
func (mi *MenuItem) SetAccelerator(accelerator string) *MenuItemParameters:
accelerator- Keyboard shortcut (e.g., “Ctrl+S”, “Cmd+Q”)
Accelerator format:
- Modifiers:
Ctrl,Cmd,Alt,Shift - Keys:
A-Z,0-9,F1-F12,Enter,Backspace, etc. - Platform: Use
Cmdon macOS,Ctrlon Windows/Linux
Example:
saveItem.SetAccelerator("Ctrl+S")quitItem.SetAccelerator("Ctrl+Q")newItem.SetAccelerator("Ctrl+N")Platform-aware example:
import "runtime"
var quitShortcut stringif runtime.GOOS == "darwin" { quitShortcut = "Cmd+Q"} else { quitShortcut = "Ctrl+Q"}quitItem.SetAccelerator(quitShortcut)SetTooltip()
Section titled “SetTooltip()”Sets a tooltip that appears when hovering over the menu item.
func (mi *MenuItem) SetTooltip(tooltip string) *MenuItemExample:
item.SetTooltip("Opens a file from disk")SetHidden()
Section titled “SetHidden()”Shows or hides the menu item.
func (mi *MenuItem) SetHidden(hidden bool) *MenuItemExample:
// Hide debug menu in productiondebugItem.SetHidden(!isDevelopment)menu.Update()Application Menu
Section titled “Application Menu”app.Menu.Set()
Section titled “app.Menu.Set()”Sets the application’s main menu bar.
func (mm *MenuManager) Set(menu *Menu)Example:
menu := app.NewMenu()
// File menufileMenu := menu.AddSubmenu("File")fileMenu.Add("New").SetAccelerator("Ctrl+N").OnClick(newFile)fileMenu.Add("Open").SetAccelerator("Ctrl+O").OnClick(openFile)fileMenu.Add("Save").SetAccelerator("Ctrl+S").OnClick(saveFile)fileMenu.AddSeparator()fileMenu.Add("Exit").SetAccelerator("Ctrl+Q").OnClick(func(ctx *application.Context) { app.Quit()})
// Edit menueditMenu := menu.AddSubmenu("Edit")editMenu.Add("Undo").SetAccelerator("Ctrl+Z").OnClick(undo)editMenu.Add("Redo").SetAccelerator("Ctrl+Y").OnClick(redo)editMenu.AddSeparator()editMenu.Add("Cut").SetAccelerator("Ctrl+X").OnClick(cut)editMenu.Add("Copy").SetAccelerator("Ctrl+C").OnClick(copy)editMenu.Add("Paste").SetAccelerator("Ctrl+V").OnClick(paste)
app.Menu.Set(menu)Platform notes:
- macOS: Menu appears in the top menu bar
- Windows/Linux: Menu appears in the window title bar
- macOS: Automatically adds application menu with app name
Context Menus
Section titled “Context Menus”app.ContextMenu.New() / app.ContextMenu.Add()
Section titled “app.ContextMenu.New() / app.ContextMenu.Add()”Create a *ContextMenu via the manager and register it under a name. ContextMenuManager.Add takes *ContextMenu — not *Menu, and there is no app.RegisterContextMenu method.
func (cm *ContextMenuManager) New() *ContextMenufunc (cm *ContextMenuManager) Add(name string, menu *ContextMenu)func (cm *ContextMenuManager) Get(name string) (*ContextMenu, bool)func (cm *ContextMenuManager) Remove(name string)Alternatively, the package-level application.NewContextMenu(name string) *ContextMenu creates and registers a context menu in one step.
Go:
// Build the context menu via the managercontextMenu := app.ContextMenu.New()contextMenu.Add("Cut").OnClick(cut)contextMenu.Add("Copy").OnClick(copy)contextMenu.Add("Paste").OnClick(paste)contextMenu.AddSeparator()contextMenu.Add("Select All").OnClick(selectAll)
// Register under a name; HTML opts into it via the CSS custom property below.app.ContextMenu.Add("editor", contextMenu)HTML / CSS:
The runtime triggers a registered context menu when the right-click target (or any ancestor) has the --custom-contextmenu CSS custom property set to that name. The optional --custom-contextmenu-data property is passed to the Go callback via ctx.ContextMenuData(). To suppress the default browser context menu, set --default-contextmenu: hide (or auto/show).
<!-- Trigger context menu on right-click --><div style="--custom-contextmenu: editor; --default-contextmenu: hide"> Right-click here for context menu</div>There is no data-wails-context-menu="..." attribute — that was never wired in the runtime.
Dynamic context menus:
// Update context menu based on selectionfunc updateContextMenu() { contextMenu := app.ContextMenu.New()
if hasSelection { contextMenu.Add("Cut").OnClick(cut) contextMenu.Add("Copy").OnClick(copy) }
contextMenu.Add("Paste").SetEnabled(hasClipboardContent).OnClick(paste)
app.ContextMenu.Add("editor", contextMenu)}System Tray Menu
Section titled “System Tray Menu”app.SystemTray.New()
Section titled “app.SystemTray.New()”Creates a new system tray icon.
func (sm *SystemTrayManager) New() *SystemTrayExample:
tray := app.SystemTray.New()SetIcon()
Section titled “SetIcon()”Sets the system tray icon.
func (st *SystemTray) SetIcon(icon []byte) *SystemTrayExample:
iconData, _ := os.ReadFile("icon.png")tray.SetIcon(iconData)SetMenu()
Section titled “SetMenu()”Sets the menu for the system tray.
func (st *SystemTray) SetMenu(menu *Menu) *SystemTrayExample:
trayMenu := app.NewMenu()trayMenu.Add("Show Window").OnClick(func(ctx *application.Context) { window.Show() window.Focus()})trayMenu.Add("Settings").OnClick(openSettings)trayMenu.AddSeparator()trayMenu.Add("Quit").OnClick(func(ctx *application.Context) { app.Quit()})
tray.SetMenu(trayMenu)SetTooltip()
Section titled “SetTooltip()”Sets the tooltip shown when hovering over the tray icon. Returns nothing.
func (st *SystemTray) SetTooltip(tooltip string)Example:
tray.SetTooltip("My Application - Running")OnClick()
Section titled “OnClick()”Handles left-click on the tray icon.
func (st *SystemTray) OnClick(callback func()) *SystemTrayExample:
tray.OnClick(func() { if window.IsVisible() { window.Hide() } else { window.Show() window.Focus() }})Complete Examples
Section titled “Complete Examples”Standard Application Menu
Section titled “Standard Application Menu”package main
import ( "github.com/wailsapp/wails/v3/pkg/application")
func createMenu(app *application.App) *application.Menu { menu := app.NewMenu()
// File menu fileMenu := menu.AddSubmenu("File") fileMenu.Add("New"). SetAccelerator("Ctrl+N"). OnClick(func(ctx *application.Context) { // Create new document }) fileMenu.Add("Open"). SetAccelerator("Ctrl+O"). OnClick(func(ctx *application.Context) { // Open file dialog }) fileMenu.Add("Save"). SetAccelerator("Ctrl+S"). OnClick(func(ctx *application.Context) { // Save document }) fileMenu.AddSeparator() fileMenu.Add("Exit").OnClick(func(ctx *application.Context) { app.Quit() })
// Edit menu editMenu := menu.AddSubmenu("Edit") editMenu.Add("Undo").SetAccelerator("Ctrl+Z") editMenu.Add("Redo").SetAccelerator("Ctrl+Y") editMenu.AddSeparator() editMenu.Add("Cut").SetAccelerator("Ctrl+X") editMenu.Add("Copy").SetAccelerator("Ctrl+C") editMenu.Add("Paste").SetAccelerator("Ctrl+V")
// View menu viewMenu := menu.AddSubmenu("View") darkMode := viewMenu.AddCheckbox("Dark Mode", false) darkMode.OnClick(func(ctx *application.Context) { // Toggle dark mode isChecked := darkMode.Checked() app.Logger.Info("Dark mode", "enabled", isChecked) }) viewMenu.AddSeparator() viewMenu.AddRadio("List View", true) viewMenu.AddRadio("Grid View", false) viewMenu.AddRadio("Detail View", false)
// Help menu helpMenu := menu.AddSubmenu("Help") helpMenu.Add("Documentation").OnClick(func(ctx *application.Context) { // Open docs }) helpMenu.Add("About").OnClick(func(ctx *application.Context) { // Show about dialog })
return menu}
func main() { app := application.New(application.Options{ Name: "Menu Demo", })
menu := createMenu(app) app.Menu.Set(menu)
window := app.Window.New() window.Show()
app.Run()}System Tray Application
Section titled “System Tray Application”func setupSystemTray(app *application.App, window application.Window) { // Create system tray tray := app.SystemTray.New()
// Set icon iconData, _ := os.ReadFile("icon.png") tray.SetIcon(iconData) tray.SetTooltip("My App - Running")
// Handle left-click on tray icon tray.OnClick(func() { if window.IsVisible() { window.Hide() } else { window.Show() window.Focus() } })
// Create tray menu trayMenu := app.NewMenu()
showItem := trayMenu.Add("Show Window") showItem.OnClick(func(ctx *application.Context) { window.Show() window.Focus() })
trayMenu.AddSeparator()
trayMenu.Add("Settings").OnClick(func(ctx *application.Context) { // Open settings window })
trayMenu.Add("About").OnClick(func(ctx *application.Context) { // Show about dialog })
trayMenu.AddSeparator()
trayMenu.Add("Quit").OnClick(func(ctx *application.Context) { app.Quit() })
tray.SetMenu(trayMenu)}Dynamic Menu Updates
Section titled “Dynamic Menu Updates”type Editor struct { app *application.App menu *application.Menu undoItem *application.MenuItem redoItem *application.MenuItem saveItem *application.MenuItem undoStack []string redoStack []string hasChanges bool}
func (e *Editor) createMenu() { e.menu = e.app.NewMenu()
fileMenu := e.menu.AddSubmenu("File") e.saveItem = fileMenu.Add("Save").SetAccelerator("Ctrl+S") e.saveItem.OnClick(func(ctx *application.Context) { e.save() })
editMenu := e.menu.AddSubmenu("Edit") e.undoItem = editMenu.Add("Undo").SetAccelerator("Ctrl+Z") e.undoItem.OnClick(func(ctx *application.Context) { e.undo() })
e.redoItem = editMenu.Add("Redo").SetAccelerator("Ctrl+Y") e.redoItem.OnClick(func(ctx *application.Context) { e.redo() })
e.updateMenuState() e.app.Menu.Set(e.menu)}
func (e *Editor) updateMenuState() { // Update menu items based on current state e.saveItem.SetEnabled(e.hasChanges) e.undoItem.SetEnabled(len(e.undoStack) > 0) e.redoItem.SetEnabled(len(e.redoStack) > 0) e.menu.Update()}
func (e *Editor) onChange() { e.hasChanges = true e.updateMenuState()}
func (e *Editor) save() { // Save logic e.hasChanges = false e.updateMenuState()}Best Practices
Section titled “Best Practices”- Use standard accelerators - Follow platform conventions (Ctrl+C for copy, etc.)
- Call Update() after changes - Menu won’t reflect changes otherwise
- Group related items - Use separators to organize menu items
- Disable unavailable actions - Don’t hide, disable with SetEnabled(false)
- Use clear labels - Be concise and descriptive
- Follow platform conventions - macOS vs Windows/Linux menu patterns
❌ Don’t
Section titled “❌ Don’t”- Don’t forget Update() - Most common mistake
- Don’t nest too deeply - Keep menus 2-3 levels maximum
- Don’t use ambiguous labels - “Process” vs “Process Document”
- Don’t overcomplicate - Keep menus simple and focused
- Don’t mix metaphors - Consistent naming and organization
Platform-Specific Notes
Section titled “Platform-Specific Notes”- Application menu automatically added with app name
- Use
Cmdinstead ofCtrlfor accelerators - “About”, “Preferences”, and “Quit” in application menu by default
Windows/Linux
Section titled “Windows/Linux”- No automatic application menu
- Use
Ctrlfor accelerators - “Exit” typically in File menu