Skip to content

MenuBar

phroun edited this page Aug 22, 2026 · 4 revisions

Wire names menubar · menu · menuitem

An application's menu bar. Three types build it: a menubar holds menus, each menu holds menuitems, and choosing an item raises a command event naming what was asked for.

mb=new menubar children={
	new menu caption="&File" wellknown="file" children={
		new menuitem caption="&New" shortcut="^N" action=app.file.new
		new menuitem caption="&Open…" shortcut="^O" action=app.file.open
		new menuitem separator
		new menuitem caption="&Quit" shortcut="^Q" action=app.quit
	}
}

A menu bar is top-level, not a window child

A menubar is not placed inside a window's children. It is built as its own top-level object in the same request, and the display adopts it as the connection's application chrome — the same way it adopts a window and a statusbar:

w=new window title="My App" width=480 height=288 main children={
	new panel layout=vbox children={ … }
}
mb=new menubar children={ … }

A window takes exactly one content trinket, so anything with several parts goes in a Panel — asking for two is an error that says so.

Properties

menubar

menubar takes no properties of its own.

It is a container and nothing else — no properties, no events, and none of the common properties either, since it is never placed anywhere. Everything worth setting is on the menus inside it.

menu

Property Type Default Meaning
after string Place this untagged menu after a well-known slot (e.g. after=file)
caption string Menu title (& marks accelerator)
wellknown string System role tag: app/file/edit/format/view/window/help

menuitem

Property Type Default Meaning
action word Command id dispatched on activation
caption string Item label (& marks accelerator)
checkable flag false Item can be checked
checked flag false Checked state
enabled flag true Item is enabled
inplace flag false Activation acts in place: the menu stays open.
separator flag false Render as a separator line
shortcut string Keyboard shortcut (e.g. "^N")
shortcuttext string Literal text for the shortcut column, for keys the host handles itself (appended after any shortcut)
wellknown string System item role: cut/copy/paste/selectall - this item BECOMES the standard one

None of the three take the common properties — there is no fg, bg, stretch or align on a menu. That is why menuitem carries an enabled of its own rather than borrowing the common one.

menubar and menuitem say so plainly:

new menubar bg=blue
  ->  property "bg" is not supported by this type

menu refuses too, but reports it as an internal type mismatch (bg: wrong target type *trinkets.Menu) rather than as the plain message. Treat it as the same refusal.

Events

command — The item was chosen. Carries the command it names rather than the item's identity, because a command is what an application binds to and the same one may be reachable from several menus.

Field Type Meaning
action word The command ID the item names.

Choosing an item raises command carrying the item's action, exactly as a Button with action= does, so a client binds handlers to command IDs without regard to whether a button, a menu item or a keyboard shortcut reached it.

conn.OnCommand("app.file.new", func() { … })

Every item raises command, whether or not you gave it an action=. An item without one is assigned a generated ID — cmd.auto.5 and the like — and that is what arrives:

new menuitem caption="Cu&t" wellknown="cut"
  ->  command with action = "cmd.auto.5"

So an unhandled item is not silent; it reports something your handler table will not recognise. Give an item an action= if you mean to act on it.

Mnemonics: & in a caption

Unlike every other trinket, menu and menuitem parse & in their caption. The marked letter becomes the accelerator and the & is removed from what is drawn:

Caption Shown
"&File" File
"Cu&t" Cut
"Save && Close" Save & Close

&& is the escape for a literal ampersand. Assignment is greedy across siblings, so an item whose marked letter is already taken falls back to another letter from its label, so marking the obvious letter on every item still resolves to a distinct set.

This markup is menu-only. A Button captioned "&Save" paints the ampersand.

Shortcuts

Three different things can fill an item's shortcut column.

Property For
shortcut A key this item binds, written in the key vocabulary — "^N", "s-Q".
shortcuttext Literal text for a key the host handles, which the toolkit does not bind but which still deserves advertising. Appended after any shortcut.
(neither) Nothing shown.

shortcut="^N" both binds the key and prints it. shortcuttext="F10" prints only — use it when something else already owns the key.

Item kinds

new menuitem separator                                     # a rule
new menuitem caption="&Word Wrap" checkable checked action=app.view.wrap
new menuitem caption="Not yet" !enabled
new menuitem caption="Stays open" inplace action=app.tweak

separator draws a rule and holds no label.

checkable / checked give the item a check mark. The item still raises command on activation; the check state is yours to keep in step by setting checked back.

inplace keeps the menu open after activation instead of dismissing it — for a run of toggles a user flips several times, like a column chooser. Escape or a click away still closes it.

!enabled greys the item and refuses activation.

Well-known roles

wellknown tags a menu or an item with a standard role, and the desktop merges it with the host's own chrome rather than showing two of everything.

On Values
menu app file edit format view window help
menuitem cut copy paste selectall

A tagged item becomes the standard one — your "Cu&t" with wellknown="cut" is the Cut command, in the place the platform expects it, rather than a second Cut beside it.

after= places an untagged menu relative to a tagged slot — after=file puts your menu just past the File menu — so a custom menu can be positioned without claiming a role it does not have.

See also

Button — the other way to raise command · StatusBar · Desktop · Templates and Aliases — for repeated menu shapes

Clone this wiki locally