fix(modals): vertically center auto-height dialogs in the window
Fixed-height overlay cards were already centered, but auto-height cards hard-anchored at 15% from the top, so shorter dialogs (e.g. Migrate to a seed wallet, Import Key, About) rendered top-heavy with a large empty area below. Center auto-height cards on last frame's measured content height (already cached per dialog id in g_overlayCardHeights). A re-opened dialog centers from frame 1; only the very first open of a given dialog this session briefly anchors near the top before it re-centers. Content taller than the window top-anchors at a 16px margin. One framework change centers every modal (verified across migrate / import-key / about / seed-backup at 100%). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1396,8 +1396,10 @@ inline bool BeginOverlayDialog(const OverlayDialogSpec& spec)
|
||||
ImGuiButtonFlags_MouseButtonRight |
|
||||
ImGuiButtonFlags_MouseButtonMiddle);
|
||||
|
||||
// Card geometry: fixed-height (large modals) is centered; auto-height reuses last frame's
|
||||
// measured content height (short dialogs get short cards), capped at the viewport ratio.
|
||||
// Card geometry: both fixed- and auto-height cards are VERTICALLY CENTERED in the window.
|
||||
// Fixed-height centers its known height; auto-height centers last frame's measured content
|
||||
// height (cached per dialog id, so a re-opened dialog is centered from frame 1 — only the very
|
||||
// first open of a given dialog this session briefly anchors near the top before it re-centers).
|
||||
float cardX = vp_pos.x + (vp_size.x - cardWidth) * 0.5f;
|
||||
float cardY, cardBottomY;
|
||||
const bool fixedHeight = (spec.cardHeight > 0.0f);
|
||||
@@ -1407,12 +1409,20 @@ inline bool BeginOverlayDialog(const OverlayDialogSpec& spec)
|
||||
cardBottomY = cardY + cardH;
|
||||
g_overlayCurrentKey.clear();
|
||||
} else {
|
||||
cardY = vp_pos.y + vp_size.y * 0.15f;
|
||||
g_overlayCurrentKey = childId;
|
||||
float ratioMaxY = vp_pos.y + vp_size.y * spec.cardBottomViewportRatio;
|
||||
auto it = g_overlayCardHeights.find(childId);
|
||||
cardBottomY = (it != g_overlayCardHeights.end() && it->second > 0.0f)
|
||||
? std::min(cardY + it->second, ratioMaxY) : ratioMaxY;
|
||||
const float measuredH = (it != g_overlayCardHeights.end()) ? it->second : 0.0f;
|
||||
if (measuredH > 0.0f) {
|
||||
// Center the measured content; if it's taller than the window, anchor at the top margin.
|
||||
cardY = (measuredH < vp_size.y - 32.0f)
|
||||
? vp_pos.y + (vp_size.y - measuredH) * 0.5f
|
||||
: vp_pos.y + 16.0f;
|
||||
cardBottomY = cardY + measuredH;
|
||||
} else {
|
||||
// First frame: content height not yet known. Anchor near the top; it re-centers next frame.
|
||||
cardY = vp_pos.y + vp_size.y * 0.15f;
|
||||
cardBottomY = vp_pos.y + vp_size.y * spec.cardBottomViewportRatio;
|
||||
}
|
||||
}
|
||||
ImVec2 cardMin(cardX, cardY), cardMax(cardX + cardWidth, cardBottomY);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user