Beginner
Dialogs & Transient UI
Modals, toasts, context menus and info popovers — the controls that appear over your layout, ordered by how much they demand of the user.
Introduction
Choosing the Right One
Four controls handle the UI that appears over your layout rather than inside it. They differ in how much they demand of the user.
| Control | Interrupts? | Use for |
|---|---|---|
Modal | Yes — blocks until answered | Decisions that must be made now |
Toast | No — dismisses itself | Confirming something already happened |
ContextMenu | Until chosen or dismissed | Actions attached to a place or object |
InfoButton | No — a popover on demand | Explaining a control without cluttering it |
Reach for the least interrupting option that works. A modal for something the user did not ask about is the most disruptive control in any interface — a toast usually says the same thing without stopping them.
1Blocking
Modal
A modal owns a title, arbitrary content, and up to two buttons.
ml::Modal confirm;
confirm.setTitle("Delete this section?");
confirm.setContent(bodyText); // any ml::Core
confirm.setConfirmLabel("Delete");
confirm.setCancelLabel("Keep");
confirm.onConfirm([&]{ deleteSection(); });
confirm.show();
| Method | Effect |
|---|---|
setTitle(text) | Heading. |
setContent(core) | Any component as the body. |
setConfirmLabel(s) | Primary button text. |
setCancelLabel(s) | Secondary button. An empty string hides it. |
onConfirm(cb) / onCancel(cb) | Outcome callbacks. |
show() | Present with the open animation. |
showImmediate() | Present with no animation. |
hide() | Dismiss. |
isVisible() | Whether it is currently up. |
Setting an empty confirm or cancel label removes that button. A modal with neither becomes a message you must dismiss another way — set at least one, or drive
hide() yourself.2Passive
Toast
A toast reports something that already happened and then removes itself.
ml::Toast toast;
toast.setMessage("Quiz submitted");
toast.setAnchor(ml::Toast::Anchor::BOTTOM);
toast.show();
// With an action:
toast.setMessage("Note deleted");
toast.setActionLabel("Undo");
toast.onDismiss([&]{ restoreNote(); });
toast.show();
| Method | Effect |
|---|---|
setMessage(text) | What happened. |
setActionLabel(s) | Optional action button. Empty hides it. |
setAnchor(TOP|BOTTOM) | Which edge it slides from. |
show() / hide() | Present and dismiss. |
onDismiss(cb) | Fires when it goes away. |
Write toast text as a completed fact — "Quiz submitted", not "Submitting quiz…". By the time it is on screen the thing has happened, and present-tense wording reads as though something is still pending.
3Contextual
Context Menu
A context menu is a list of actions shown at a point — typically where the user right-clicked.
ml::ContextMenu menu;
menu.addItem("Rename", [&]{ beginRename(); });
menu.addItem("Duplicate", [&]{ duplicate(); });
menu.addItem("Delete", [&]{ confirmDelete(); });
menu.showAt(mousePosition);
| Method | Effect |
|---|---|
addItem(label, action) | Append an entry. |
clearItems() | Empty it — rebuild per invocation when the actions vary. |
showAt(pos) | Present at a screen position. |
hide() | Dismiss. |
setSearchable(bool) | Add a filter field for long menus. |
setMaxVisibleItems(n) | Scroll beyond this many. |
setFixedWidth(w) | Pin the width instead of fitting content. |
onClose(cb) | Fires on dismissal, chosen or not. |
For menus whose entries depend on what was clicked, call
clearItems() and rebuild before each showAt. A stale menu offering actions that no longer apply is worse than no menu.4Help
Info Button
An info button is a small circular ? that reveals a popover — help text that would otherwise crowd the control it explains.
ml::InfoButton help;
help.setText("Students see this name in their course list.");
help.setPopoverWidth(240.f);
help.setRightOf(courseNameField, 8.f);
| Method | Effect |
|---|---|
setText(help) | Popover body. |
setPopoverWidth(w) | Wrap width. |
setRadius(r) | Size of the button itself. |
open() / close() / toggle() | Drive it programmatically. |
Use it for genuinely optional detail. If a user must read the text to use the control correctly, it belongs in a visible label, not hidden behind a button.