From 00ee61fe6483dc3505b4531113b0142c9a2213f9 Mon Sep 17 00:00:00 2001 From: DanS Date: Thu, 11 Jun 2026 17:38:19 -0500 Subject: [PATCH] fix(dialogs): size the overlay glass card to its content MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- src/ui/material/draw_helpers.h | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/ui/material/draw_helpers.h b/src/ui/material/draw_helpers.h index 94837ca..d78fdac 100644 --- a/src/ui/material/draw_helpers.h +++ b/src/ui/material/draw_helpers.h @@ -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 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)