Skip to content

Context Menus

MorquinDevlar edited this page Aug 20, 2026 · 1 revision

Context Menus

mdw.showContextMenu(title, items, x, y) opens a transient action menu - the generic form of "click a thing, act on it" (inventory items, quest rows) - so your widget content carries one link per item instead of a scatter of per-action links:

widget.content:dechoLink("<200,200,200>iron sword", function()
  mdw.showContextMenu("iron sword", {
    { label = "Wield", onClick = function() send("wield sword") end },
    { separator = true },
    { label = "Drop",  onClick = function() send("drop sword") end },
  })
end, "item actions", true)
  • items is an array of { label, onClick } action rows and { separator = true } dividers.
  • title (optional) heads the menu above a divider line. A string renders in the theme accent; pass { text = "iron sword", color = { 200, 200, 200 } } to render it in the clicked item's own color. Titles longer than contextMenuTitleMax (40 chars) are truncated with ....
  • x, y position the top-left corner and default to the mouse position, so a click handler can simply call mdw.showContextMenu(title, items). The menu is kept fully on screen when opened near a window edge.

The menu hides before running the clicked action (the action may open another menu or repaint the widget the click came from). It closes on click-away, is exclusive with the header dropdowns (opening one closes the other), follows the theme, and is torn down with the rest of the UI. It is drawn as a rounded card in the widget-content font (contentFontSize), not the header-menu font, because it floats over the content it acts on.

Checkbox (settings) menus

Two extras turn it into the web-client-style settings menu:

  • A row with checked (boolean) draws a [x] / [ ] text checkbox before its label.
  • A row with keepOpen = true re-opens the menu in place after its onClick, so the fresh checked state shows.

For that to work the items must be re-evaluated on every render: pass a function returning the array instead of the array itself.

mdw.gameSettings["MyGame"] = mdw.gameSettings["MyGame"] or { balance = true }

local function settingsItems()
  return {
    { label = "Show balance", checked = mdw.gameSettings.MyGame.balance, keepOpen = true,
      onClick = function()
        mdw.gameSettings.MyGame.balance = not mdw.gameSettings.MyGame.balance
        mdw.saveLayout()
        repaintPromptBar()
      end },
  }
end

Two buttons hang such menus where the web clients put them - a vertical-ellipsis in the prompt bar's right corner and in a widget's top-right:

mdw.setPromptBarMenu(settingsItems, "Prompt Bar")    -- nil removes; survives rebuilds
mdw.setWidgetMenu("Combat", settingsItems, "Combat") -- dies with the widget

The prompt bar reserves a column for its button so the gauge row and prompt text stop short of it. mdw.gameSettings (see Layout Persistence) is the natural home for the toggles themselves.

Related options: contextMenuItemHeight, contextMenuPadding, contextMenuPaddingLeft, contextMenuMinWidth, contextMenuTitleMax in Configuration.

Clone this wiki locally