Menus
Perry supports native menu bars, context menus, and toolbar items across all platforms.
Menu Bar
Create a native application menu bar:
import { App, menuBarCreate, menuBarAddMenu, menuAddItem, menuAddSeparator, menuAddSubmenu, menuBarAttach } from "perry/ui";
App("Menu Demo", () => {
const menuBar = menuBarCreate();
// File menu
const fileMenu = menuBarAddMenu(menuBar, "File");
menuAddItem(fileMenu, "New", () => newDoc(), "n"); // Cmd+N
menuAddItem(fileMenu, "Open", () => openDoc(), "o"); // Cmd+O
menuAddSeparator(fileMenu);
menuAddItem(fileMenu, "Save", () => saveDoc(), "s"); // Cmd+S
menuAddItem(fileMenu, "Save As...", () => saveAs(), "S"); // Cmd+Shift+S
// Edit menu
const editMenu = menuBarAddMenu(menuBar, "Edit");
menuAddItem(editMenu, "Undo", () => undo(), "z");
menuAddItem(editMenu, "Redo", () => redo(), "Z"); // Cmd+Shift+Z
menuAddSeparator(editMenu);
menuAddItem(editMenu, "Cut", () => cut(), "x");
menuAddItem(editMenu, "Copy", () => copy(), "c");
menuAddItem(editMenu, "Paste", () => paste(), "v");
// Submenu
const viewMenu = menuBarAddMenu(menuBar, "View");
const zoomSubmenu = menuAddSubmenu(viewMenu, "Zoom");
menuAddItem(zoomSubmenu, "Zoom In", () => zoomIn(), "+");
menuAddItem(zoomSubmenu, "Zoom Out", () => zoomOut(), "-");
menuAddItem(zoomSubmenu, "Actual Size", () => zoomReset(), "0");
menuBarAttach(menuBar);
// ... rest of UI
});
Menu Bar Functions
menuBarCreate()— Create a new menu barmenuBarAddMenu(menuBar, title)— Add a top-level menu, returns menu handlemenuAddItem(menu, label, callback, shortcut?)— Add a menu item with optional keyboard shortcutmenuAddSeparator(menu)— Add a separator linemenuAddSubmenu(menu, title)— Add a submenu, returns submenu handlemenuBarAttach(menuBar)— Attach the menu bar to the application
Keyboard Shortcuts
The 4th argument to menuAddItem is an optional keyboard shortcut:
| Shortcut | macOS | Other |
|---|---|---|
"n" | Cmd+N | Ctrl+N |
"S" | Cmd+Shift+S | Ctrl+Shift+S |
"+" | Cmd++ | Ctrl++ |
Uppercase letters imply Shift.
Context Menus
Right-click menus on widgets:
import { Text, contextMenu } from "perry/ui";
const label = Text("Right-click me");
contextMenu(label, [
{ label: "Copy", action: () => copyText() },
{ label: "Paste", action: () => pasteText() },
{ separator: true },
{ label: "Delete", action: () => deleteItem() },
]);
Toolbar
Add a toolbar to the window:
import { App, toolbarCreate, toolbarAddItem } from "perry/ui";
App("Toolbar Demo", () => {
const toolbar = toolbarCreate();
toolbarAddItem(toolbar, "New", () => newDoc());
toolbarAddItem(toolbar, "Save", () => saveDoc());
toolbarAddItem(toolbar, "Run", () => runCode());
// ... rest of UI
});
Platform Notes
| Platform | Menu Bar | Context Menu | Toolbar |
|---|---|---|---|
| macOS | NSMenu | NSMenu | NSToolbar |
| iOS | — (no menu bar) | UIMenu | UIToolbar |
| Windows | HMENU/SetMenu | — | Horizontal layout |
| Linux | GMenu/set_menubar | — | HeaderBar |
| Web | DOM | DOM | DOM |
iOS: Menu bars are not applicable. Use toolbar and navigation patterns instead.
Next Steps
- Events — Keyboard shortcuts and interactions
- Dialogs — File dialogs and alerts
- Toolbar and navigation