Dialogs and Context Menus
Dialogs interrupt the current workflow for a decision or short input. ContextMenu exposes temporary actions at a pointer location. Routine success and progress belong in Feedback and Progress.
Reuse One Dialog
local dialog = frame:addDialog({
boxWidth = 32,
titleBackground = colors.blue,
titleForeground = colors.white,
boxBackground = colors.lightGray,
boxForeground = colors.black,
})Add it to the root when its backdrop should cover the complete application.
Alert, Confirm, and Prompt
dialog:alert("Connection", "The remote computer is unavailable.")dialog:confirm("Delete task?", "This cannot be undone.", function(yes)
if yes then deleteTask() end
taskList:focus()
end)
dialog:focus()dialog:prompt("Rename", "New task name:", currentName, function(value)
if value and value:match("%S") then currentName = value end
renameButton:focus()
end)Prompt returns nil for Cancel. An empty string is a submitted value.
Alert and Confirm do not automatically claim keyboard focus. Focus the Dialog or build a custom overlay when full keyboard navigation is required.
Every closure fires close:
dialog:onClose(function(self, result)
cleanup(result)
end)Manual close() fires this event but not a helper-specific callback.
Context Menu
local menu = frame:addContextMenu()
menu:setItems({
{ text = "Rename", callback = renameSelected },
{ separator = true },
{ text = "Delete", callback = deleteSelected },
})
menu:showAt(20, 8)Coordinates passed to a root menu are root-local. Close or replace other overlays so temporary layers do not compete.
Runnable Dialog
local basalt = require("basalt")
local frame = basalt.getMainFrame()
frame.background = colors.black
local status = frame:addLabel({
x = 2,
y = 2,
width = 45,
height = 3,
text = "Choose an action.",
foreground = colors.lightGray,
})
local dialog = frame:addDialog({
boxWidth = 32,
titleBackground = colors.blue,
boxBackground = colors.lightGray,
boxForeground = colors.black,
})
frame:addButton({
x = 2,
y = 6,
width = 12,
height = 2,
text = "Confirm",
}):onClick(function()
dialog:confirm("Continue?", "Apply the selected action?", function(yes)
status.text = yes and "Confirmed" or "Cancelled"
status.foreground = yes and colors.lime or colors.orange
end)
dialog:focus()
end)
frame:addButton({
x = 16,
y = 6,
width = 12,
height = 2,
text = "Prompt",
}):onClick(function()
dialog:prompt("Rename", "Enter a name:", "", function(value)
status.text = value and ("Name: " .. value) or "Prompt cancelled"
end)
end)
frame:addButton({
x = 38,
y = 14,
width = 12,
height = 2,
text = "Exit",
background = colors.red,
}):onClick(function()
basalt.stop()
end)
basalt.run()Common Mistakes
- Use inline status or Toast for routine success.
- Keep destructive work inside the confirmation callback.
- Restore useful focus after a Dialog closes.
- Treat empty Prompt text separately from Cancel.
- Do not assume pointer modality also provides keyboard modality.
Related Guides and API
Next Steps
Use Feedback and Progress for non-blocking status, notifications, and long-running work.