Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/The-Young-Maker/OpenMenuOS/llms.txt

Use this file to discover all available pages before exploring further.

The PopupManager class gives you a complete, non-blocking dialog system with five built-in visual styles. Each popup type carries its own color scheme and default title so you can surface feedback, confirmations, and errors with a single method call — no manual drawing required. OpenMenuOS ships five popup types, each with a distinct color theme:
TypeColorDefault titleNotes
INFOBlue”Information”General messages
SUCCESSGreen”Success”Auto-closes after ~3 s
WARNINGOrange”Warning”Requires user dismissal
ERRORRed”Error”Requires user dismissal
QUESTIONCyan”Question”Shows Yes / No buttons

Quick one-liner methods

Each type has a dedicated static method. The title parameter is optional on all of them.
PopupManager::showInfo("Operation completed successfully!", "Info Demo");

Advanced configuration with PopupConfig

When the one-liners aren’t enough, build a PopupConfig struct and pass it to PopupManager::show().
PopupConfig config;
config.title          = "Custom Popup";
config.message        = "This popup closes on its own after 5 seconds.";
config.type           = PopupType::INFO;
config.autoClose      = true;
config.autoCloseDelay = 5000;       // milliseconds
config.customColor    = 0x07E0;     // RGB565 green — overrides type default
PopupManager::show(config);
All fields with their defaults:
FieldTypeDefaultPurpose
titleconst char*nullptr (uses type default)Header text
messageconst char*nullptrBody text (required)
typePopupTypePopupType::INFOColor scheme and icon
showButtonsbooltrueShow action buttons
showCancelButtonboolfalseAdd a Cancel / No button
autoCloseboolfalseClose automatically
autoCloseDelayuint32_t3000Auto-close delay (ms)
customColoruint16_t0 (uses type default)Override header color
customIconconst uint16_t*nullptrCustom icon pixel data
customIconWidthuint16_t0Icon width in pixels
customIconHeightuint16_t0Icon height in pixels

The non-blocking pattern

PopupManager is non-blocking. Calling showInfo() or showQuestion() queues the popup but does not wait for a response. You poll for the result on every iteration of loop() using PopupManager::update().
PopupManager::update() must be called before menu.loop(). The update method both renders the active popup and intercepts input. Calling it after menu.loop() can cause the underlying menu to process button presses that were meant for the popup.
void loop() {
  PopupResult popupResult = PopupManager::update();

  menu.loop(); // safe — popup has already consumed any relevant input

  if (popupResult != PopupResult::NONE) {
    switch (popupResult) {
      case PopupResult::OK:
        Serial.println("User clicked OK/Yes");
        // your confirmation logic here
        break;
      case PopupResult::CANCEL:
        Serial.println("User clicked Cancel/No");
        // your cancellation logic here
        break;
      default:
        break;
    }
  }
}

PopupResult enum

PopupManager::update() returns one value per call:
ValueMeaning
PopupResult::NONENo popup is active, or the popup is still waiting for input
PopupResult::OKUser pressed OK or Yes
PopupResult::CANCELUser pressed Cancel or No
PopupResult::YESAlias for OK in question dialogs
PopupResult::NOAlias for CANCEL in question dialogs
A non-NONE result is delivered exactly once — on the loop iteration in which the user interacts with the popup. Subsequent calls return PopupResult::NONE until a new popup is shown.

Input blocking

While a popup is visible, PopupManager::update() captures all button and encoder events before menu.loop() sees them. This prevents accidental navigation in the underlying menu when the user dismisses a dialog. You can also check PopupManager::isActive() if you want to gate other logic:
void loop() {
  PopupResult popupResult = PopupManager::update();

  if (!PopupManager::isActive()) {
    menu.loop();
  }

  if (popupResult != PopupResult::NONE) {
    // handle result
  }
}

Encoder support

When a rotary encoder is configured with menu.setEncoderPin(clk, dt), it works inside popups too:
  • Rotate the encoder to move the highlight between the OK and Cancel buttons.
  • Press the encoder button (select) to confirm the highlighted choice.
No extra configuration is needed — encoder support in popups is automatic once the encoder pins are registered.

Confirmation dialogs with showQuestion

showQuestion is the standard pattern for any action that needs explicit user approval:
void resetDevice() {
  PopupManager::showQuestion(
    "This will restart the device.\nContinue?",
    "Reset Device"
  );
}

void loop() {
  PopupResult result = PopupManager::update();
  menu.loop();

  if (result == PopupResult::OK) {
    // user confirmed — proceed with the destructive action
    ESP.restart();
  }
}
showQuestion automatically adds both an OK/Yes and a Cancel/No button. You do not need to set showCancelButton in a PopupConfig manually when using this helper.

Additional state methods

// Check programmatically whether a popup is currently on screen
bool active = PopupManager::isActive();

// Dismiss the current popup from code (e.g., on a timeout you control yourself)
PopupManager::hide();

Build docs developers (and LLMs) love