fix(dialogs): size the overlay glass card to its content
The overlay dialog's content child is AutoResizeY, but the glass card behind it was drawn to a fixed viewport ratio — leaving a tall band of empty glass below short dialogs (e.g. the key-export modal had a gap under its Close button). Measure the rendered card height each frame and reuse it next frame to draw the glass to the content; fall back to (and stay capped at) the ratio so tall dialogs are unchanged and can't run off-screen. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -916,6 +916,12 @@ inline bool DrawDialogTitleBar(const char* title, bool* p_open, ImU32 accent_col
|
||||
// Creates a fullscreen semi-transparent overlay with a centered card dialog.
|
||||
// Similar to the shutdown screen pattern but for interactive dialogs.
|
||||
|
||||
// Per-dialog content height (keyed by the child's id) measured at the end of each frame, so the next
|
||||
// frame can size the glass card to its content instead of a fixed viewport band. g_overlayCurrentKey
|
||||
// carries the active dialog's key from BeginOverlayDialog to EndOverlayDialog (overlays don't nest).
|
||||
inline std::unordered_map<std::string, float> g_overlayCardHeights;
|
||||
inline std::string g_overlayCurrentKey;
|
||||
|
||||
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)
|
||||
{
|
||||
@@ -977,10 +983,22 @@ inline bool BeginOverlayDialog(const char* title, bool* p_open, float cardWidth
|
||||
// Calculate card position (centered)
|
||||
float cardX = vp_pos.x + (vp_size.x - cardWidth) * 0.5f;
|
||||
float cardY = vp_pos.y + vp_size.y * 0.15f;
|
||||
|
||||
|
||||
// Size the card height to its content. The content child below is AutoResizeY, so a glass card
|
||||
// drawn to a fixed viewport ratio left a tall band of empty glass under short dialogs. Reuse the
|
||||
// height the child reported LAST frame (content is stable frame-to-frame, so no visible lag) and
|
||||
// fall back to the ratio on the first frame. Still capped at the ratio so a very tall dialog can't
|
||||
// run off-screen (its content spills/scrolls as before).
|
||||
g_overlayCurrentKey = childId;
|
||||
float ratioMaxY = vp_pos.y + vp_size.y * cardBottomViewportRatio;
|
||||
auto prevHeightIt = g_overlayCardHeights.find(childId);
|
||||
float cardBottomY = (prevHeightIt != g_overlayCardHeights.end() && prevHeightIt->second > 0.0f)
|
||||
? std::min(cardY + prevHeightIt->second, ratioMaxY)
|
||||
: ratioMaxY;
|
||||
|
||||
// Draw glass card background
|
||||
ImVec2 cardMin(cardX, cardY);
|
||||
ImVec2 cardMax(cardX + cardWidth, vp_pos.y + vp_size.y * cardBottomViewportRatio);
|
||||
ImVec2 cardMax(cardX + cardWidth, cardBottomY);
|
||||
|
||||
// Card background with glass effect
|
||||
GlassPanelSpec cardGlass;
|
||||
@@ -1020,6 +1038,11 @@ inline bool BeginOverlayDialog(const char* title, bool* p_open, float cardWidth
|
||||
inline void EndOverlayDialog()
|
||||
{
|
||||
ImGui::EndChild();
|
||||
// Remember the rendered card height (the child is the last item) so the next frame's
|
||||
// BeginOverlayDialog can size the glass to the content — kills the empty band under short dialogs.
|
||||
if (!g_overlayCurrentKey.empty()) {
|
||||
g_overlayCardHeights[g_overlayCurrentKey] = ImGui::GetItemRectSize().y;
|
||||
}
|
||||
ImGui::PopStyleColor(); // ChildBg
|
||||
ImGui::PopStyleVar(2); // ChildRounding, WindowPadding (for child)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user