feat(ui): layout polish — fill dead space, pair/box/collapse, warning weight, dialog glass

Implements the layout-improvement suggestions from the layout audit (visual arrangement
only; no functionality added or removed):

- Send/Receive: the recent-activity list now grows to fill the space below the fixed
  compose/receive card (more history visible), with a centered empty-state when there is
  none — instead of leaving dead canvas.
- Shield/Merge: pair the Fee and UTXO-Limit fields on one row to tighten vertical rhythm.
- Market: extend + frame the portfolio group-list as one contained panel (with a bottom
  edge) and center its empty-state, closing the previously un-anchored gap.
- Overlay dialogs: raise the card glass fill/border alpha (35/50 -> 60/90 of 255) so the
  dialog card reads as a distinct surface over busy backdrops (global, all overlays).
- Wallets: size the list height to the actual wallet count instead of always reserving 7
  rows, removing the large gap before the scan/create prompts (still scrolls when many).
- Contacts: width-aware address truncation shows more of the address on wide rows.
- Transfer Funds: give the "sends the full balance" warning a warning icon + color so the
  stakes stand out from the neutral result-preview lines.
- First-run wizard: collapse a completed Step 1 (Appearance) to the compact pill like
  Step 2, so a finished step is no longer taller than the active one.
- Explorer: distribute the Chain card's two stats to match the density of the sibling
  metrics grid.
- Validate Address: a "Results will appear here" caption fills the pre-interaction blank.
- Change Passphrase: add the warning banner its sibling security dialogs have.
- Migration ShowSeed: box the 24-word mnemonic grid (a GlassSectionScope behind the
  existing RenderSeedWordGrid) so the critical secret reads as a distinct artifact —
  purely visual, no seed/logic/state change.

Verified at 1280 across full-node + Lite + Windows (ctest green) and an adversarial diff
review (clean). New i18n key backfilled into all 8 languages.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-19 13:56:13 -05:00
co-authored by Claude Opus 4.8
parent d5c30237d2
commit 8778398d31
22 changed files with 189 additions and 59 deletions
+49 -22
View File
@@ -294,29 +294,43 @@ void App::renderFirstRunWizard() {
{
int state = cardState(0);
bool isFocused = (state == 1);
bool isCollapsed = (state == 2); // Completed: minimize to a compact pill (mirrors Card 1)
float cx = leftX + cardPad;
float cy = card0Top + cardPad;
float contentW = colW - 2 * cardPad;
// Step indicator
{
// Step indicator + title (inline when collapsed)
if (isCollapsed) {
// Compact single-line: check icon + "Step 1" + "Appearance"
float iconW = iconFont->CalcTextSizeA(iconFont->LegacySize, FLT_MAX, 0, stepIcon(state)).x;
dl->AddText(iconFont, iconFont->LegacySize, ImVec2(cx, cy), dimCol, stepIcon(state));
dl->AddText(captionFont, captionFont->LegacySize, ImVec2(cx + iconW + 4.0f * dp, cy), dimCol, TR("wiz_step1"));
cy += captionFont->LegacySize + 6.0f * dp;
}
float labelX = cx + iconW + 4.0f * dp;
dl->AddText(captionFont, captionFont->LegacySize, ImVec2(labelX, cy), dimCol, TR("wiz_step1"));
float step1W = captionFont->CalcTextSizeA(captionFont->LegacySize, FLT_MAX, 0, TR("wiz_step1")).x;
float titleX = labelX + step1W + 12.0f * dp;
dl->AddText(bodyFont, bodyFont->LegacySize, ImVec2(titleX, cy), dimCol, TR("wiz_appearance"));
cy += captionFont->LegacySize + 4.0f * dp;
} else {
// Step indicator
{
float iconW = iconFont->CalcTextSizeA(iconFont->LegacySize, FLT_MAX, 0, stepIcon(state)).x;
dl->AddText(iconFont, iconFont->LegacySize, ImVec2(cx, cy), dimCol, stepIcon(state));
dl->AddText(captionFont, captionFont->LegacySize, ImVec2(cx + iconW + 4.0f * dp, cy), dimCol, TR("wiz_step1"));
cy += captionFont->LegacySize + 6.0f * dp;
}
// Title
{
const char* t = TR("wiz_appearance");
dl->AddText(titleFont, titleFont->LegacySize, ImVec2(cx, cy), textCol, t);
cy += titleFont->LegacySize + 10.0f * dp;
}
// Title
{
const char* t = TR("wiz_appearance");
dl->AddText(titleFont, titleFont->LegacySize, ImVec2(cx, cy), textCol, t);
cy += titleFont->LegacySize + 10.0f * dp;
}
// Separator
dl->AddLine(ImVec2(cx, cy), ImVec2(cx + contentW, cy),
(textCol & 0x00FFFFFF) | IM_COL32(0,0,0,40), 1.0f * dp);
cy += 14.0f * dp;
// Separator
dl->AddLine(ImVec2(cx, cy), ImVec2(cx + contentW, cy),
(textCol & 0x00FFFFFF) | IM_COL32(0,0,0,40), 1.0f * dp);
cy += 14.0f * dp;
}
float& wiz_blur_amount = wizardUi.blur_amount;
bool& wiz_theme_effects = wizardUi.theme_effects;
@@ -352,6 +366,9 @@ void App::renderFirstRunWizard() {
wiz_appearance_init = true;
}
// Controls: rendered for the focused and upcoming states so content is visible under
// the dim overlay; skipped entirely once completed so the card shrinks to a compact pill.
if (!isCollapsed) {
// Render controls always so content is visible under the dim
// overlay when not focused; disable interaction when not active.
ImGui::BeginDisabled(!isFocused);
@@ -668,13 +685,21 @@ void App::renderFirstRunWizard() {
cy += btnH;
}
cy += cardPad;
// Lock card height to the tallest content ever seen
float& card0MaxH = wizardUi.card0_max_h;
card0MaxH = std::max(card0MaxH, cy - card0Top);
card0Bot = card0Top + card0MaxH;
} // if (!isCollapsed)
// Card 0 finalization deferred until after cards 1+2 are sized
cy += cardPad;
// Lock card height to the tallest content ever seen (but not when collapsed)
float& card0MaxH = wizardUi.card0_max_h;
if (isCollapsed) {
// Completed: finalize immediately as a compact pill (do not stretch to the
// right column height, and skip the deferred stretch below).
card0Bot = card0Top + (cy - card0Top);
finalizeCard(leftX, colW, card0Top, card0Bot, state);
} else {
card0MaxH = std::max(card0MaxH, cy - card0Top);
card0Bot = card0Top + card0MaxH;
// Card 0 finalization deferred until after cards 1+2 are sized
}
}
@@ -1447,7 +1472,9 @@ void App::renderFirstRunWizard() {
}
// --- Deferred Card 0 finalization: match right column total height ---
{
// Only for the focused/upcoming Appearance card; a completed one was already finalized
// above as a compact pill and must not be re-stretched.
if (cardState(0) != 2) {
float rightColBot = card2Bot;
if (rightColBot > card0Bot) card0Bot = rightColBot;
finalizeCard(leftX, colW, card0Top, card0Bot, cardState(0));