feat(ui): float all modals card-less like Manage Portfolio

Drop the glass card + boxed title bar from every dialog so content floats
directly on the blur backdrop under a plain h6 heading — the Manage-Portfolio
look — unifying the whole modal system on one visual language (reverses the
earlier card-for-small / float-for-large split).

- Framework: the positional BeginOverlayDialog overload (used by all ~34 card
  dialogs) now defaults to floatingContent + plainHeading (draw_helpers.h). The
  9 spec-form BlurFloat dialogs are unchanged; any dialog can still opt back to a
  card via an explicit OverlayStyle::GlassCard spec. Authored widths are kept
  (floating never resizes), so width-coupled layouts are unaffected.
- Dedup: the framework h6 title made each dialog's own repeated title heading
  redundant. Removed the duplicate body heading from Import/Export key, Backup,
  daemon update, seed backup, seed migration, Defender-blocked (app.cpp),
  Wallets, and the send-confirm popup.
- Close paths: dropping the title-bar close X is covered — every dialog has a
  footer button and/or the framework's outside-click dismiss (all pass p_open);
  send-confirm keeps Esc + Confirm/Cancel.

Verified via the headless full UI sweep on dark + light: 17 modal surfaces float
card-less with a single clean heading, nothing clipped, close controls present.
Build clean, ctest passes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-09 21:57:04 -05:00
parent b70f1ae643
commit e7a3f90102
4 changed files with 8 additions and 26 deletions

View File

@@ -2743,8 +2743,6 @@ void App::renderImportKeyDialog()
return;
}
ui::material::Type().text(ui::material::TypeStyle::H6, "Import Private Key");
ImGui::Dummy(ImVec2(0, ui::Layout::spacingSm()));
ImGui::TextWrapped("Enter a private key to import. The wallet will rescan the blockchain for transactions.");
ImGui::Spacing();
@@ -2847,9 +2845,7 @@ void App::renderExportKeyDialog()
return;
}
ui::material::Type().text(ui::material::TypeStyle::H6, "Export Private Key");
ImGui::Dummy(ImVec2(0, ui::Layout::spacingSm()));
ImGui::TextColored(ImVec4(0.9f, 0.4f, 0.4f, 1.0f),
ImGui::TextColored(ImVec4(0.9f, 0.4f, 0.4f, 1.0f),
"WARNING: Anyone with this key can spend your coins!");
ImGui::Spacing();
@@ -2922,8 +2918,6 @@ void App::renderBackupDialog()
return;
}
ui::material::Type().text(ui::material::TypeStyle::H6, "Backup Wallet");
ImGui::Dummy(ImVec2(0, ui::Layout::spacingSm()));
ImGui::TextWrapped("Export all private keys to a file. Keep this file secure!");
ImGui::Spacing();
@@ -2998,8 +2992,6 @@ void App::renderDaemonUpdatePrompt()
if (!ui::material::BeginOverlayDialog(TR("daemon_update_title"), &show_daemon_update_prompt_, 520.0f, 0.94f))
return;
const float dp = ui::Layout::dpiScale();
ui::material::Type().text(ui::material::TypeStyle::H6, TR("daemon_update_title"));
ImGui::Dummy(ImVec2(0, ui::Layout::spacingSm()));
ImGui::TextWrapped("%s", TR("daemon_update_body"));
ImGui::Spacing();
ImGui::PushStyleColor(ImGuiCol_Text, ui::material::OnSurfaceMedium());
@@ -3071,8 +3063,6 @@ void App::renderSeedBackupDialog()
return;
}
ui::material::Type().text(ui::material::TypeStyle::H6, TR("seed_backup_title"));
ImGui::Dummy(ImVec2(0, ui::Layout::spacingSm()));
// Button widths are logical px; BeginOverlayDialog scales the card by dpiScale() so scale these
// to match (raw widths render small/left-packed at higher DPI / font scale).
const float dp = ui::Layout::dpiScale();
@@ -3158,8 +3148,6 @@ void App::renderSeedMigrationDialog()
// BeginOverlayDialog scales the card by dpiScale(); the button widths below are authored in
// logical px and must be scaled the same way or they render small/left-packed at higher DPI.
const float dp = ui::Layout::dpiScale();
ui::material::Type().text(ui::material::TypeStyle::H6, TR("mig_title"));
ImGui::Dummy(ImVec2(0, ui::Layout::spacingSm()));
switch (seed_migration_step_) {
case SeedMigrationStep::Intro: {
@@ -3447,9 +3435,6 @@ void App::renderAntivirusHelpDialog()
return;
}
ui::material::Type().text(ui::material::TypeStyle::H6, "Windows Defender Blocked xmrig");
ImGui::Dummy(ImVec2(0, ui::Layout::spacingSm()));
ImGui::TextWrapped(
"Mining software is often flagged as potentially unwanted. "
"Follow these steps to enable pool mining:");

View File

@@ -1462,10 +1462,10 @@ inline bool BeginOverlayDialog(const OverlayDialogSpec& spec)
return childVisible;
}
// Positional overload — the default look for the app's dialogs: a card (auto-height, so small
// dialogs stay small) on the live-blur backdrop. The card renders opaque via the sole-consumer
// fallback (glass would thrash the single-slot blur cache against the radius-64 backdrop). A dialog
// that wants the old opaque scrim (no blur) can pass a spec with blurBackdrop = false.
// Positional overload — the default look for the app's dialogs: content floats directly on the
// live-blur backdrop (no glass card) under a plain h6 heading, matching the Manage-Portfolio
// editor. Auto-height keeps short dialogs short. A dialog that needs the old contained card can
// pass an explicit OverlayDialogSpec with style = OverlayStyle::GlassCard.
inline bool BeginOverlayDialog(const char* title, bool* p_open, float cardWidth = 460.0f,
float scrimOpacity = 0.92f, float cardBottomViewportRatio = 0.85f,
const char* idSuffix = nullptr)
@@ -1473,7 +1473,9 @@ inline bool BeginOverlayDialog(const char* title, bool* p_open, float cardWidth
OverlayDialogSpec s;
s.title = title; s.p_open = p_open; s.cardWidth = cardWidth;
s.scrimOpacity = scrimOpacity; s.cardBottomViewportRatio = cardBottomViewportRatio; s.idSuffix = idSuffix;
s.blurBackdrop = true;
s.blurBackdrop = true;
s.floatingContent = true; // no glass card — content floats on the blur
s.plainHeading = true; // h6 heading instead of the boxed title bar (drops the ✕)
return BeginOverlayDialog(s);
}

View File

@@ -705,9 +705,6 @@ void RenderSendConfirmPopup(App* app) {
float popW = ImGui::GetContentRegionAvail().x;
ImDrawList* popDl = ImGui::GetWindowDrawList();
Type().text(TypeStyle::H6, TR("confirm_transaction"));
ImGui::Dummy(ImVec2(0, Layout::spacingSm()));
float addrCardH = std::max(schema::UI().drawElement("tabs.send", "confirm-addr-card-min-height").size, schema::UI().drawElement("tabs.send", "confirm-addr-card-height").size * popVs);
float popGlassRound = Layout::glassRounding() * S.drawElement("tabs.send", "confirm-glass-rounding-ratio").size;

View File

@@ -52,8 +52,6 @@ public:
if (s_needScan) { scan(); s_needScan = false; }
if (BeginOverlayDialog(TR("wallets_title"), &s_open, 780.0f, 0.94f)) {
Type().text(TypeStyle::H6, TR("wallets_title"));
ImGui::Dummy(ImVec2(0, Layout::spacingXs()));
Type().textColored(TypeStyle::Caption, OnSurfaceMedium(), TR("wallets_intro"));
ImGui::Dummy(ImVec2(0, Layout::spacingSm()));