fix(wallets): roomier cards, no spurious scrollbar

Two issues on the card list: it showed a scrollbar (and clipped the last card)
with only a few wallets, and the cards felt cramped.

- Scrollbar: the per-card advance added a trailing gap after EVERY card (incl.
  the last) and ImGui inserted its default ItemSpacing between the Dummy items,
  so the content ran ~1 gap taller than the child's height budget -> overflow ->
  scrollbar + clipped card. Zero ItemSpacing inside the list child, register each
  card's footprint with a Dummy, and gap only BETWEEN cards (no trailing gap), so
  the content matches the budget exactly. Sized the list to fit up to 7 cards
  before it scrolls.
- Roominess: bigger name (subtitle1), more vertical padding (spacingMd), and a
  touch more space after the icon.
- Removed the full-card InvisibleButton (hover is IsMouseHoveringRect again): its
  overlap with the action button tripped ImGui's ConfigDebugHighlightIdConflicts,
  drawing a red debug border around the list at 150% DPI.

Verified via the headless sweep at 100% and font_scale 1.5 — no scrollbar, no red
border, cards fully visible with breathing room.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-10 02:50:19 -05:00
parent e010822a74
commit 5eff3adc3c

View File

@@ -56,14 +56,16 @@ public:
// ---- Content-sized card: a stack of wallet cards, sized to the wallet count (up to
// kMaxVisibleRows, then the list scrolls). Computed from the KNOWN row count so the
// dialog stays fixed-height (no auto-height feedback that slid content off on a move). --
const int kMaxVisibleRows = 6;
ImFont* nameFont = Type().body1();
const int kMaxVisibleRows = 7;
ImFont* nameFont = Type().subtitle1();
ImFont* metaFont = Type().caption();
const int visRows = std::min(std::max(1, (int)s_rows.size()), kMaxVisibleRows);
const float cardPadY = Layout::spacingSm();
const float walRowH = cardPadY * 2.0f + nameFont->LegacySize + Layout::spacingXs() + metaFont->LegacySize;
const float cardPadY = Layout::spacingMd(); // roomier cards (was spacingSm)
const float walRowH = cardPadY * 2.0f + nameFont->LegacySize + Layout::spacingSm() + metaFont->LegacySize;
const float cardGap = Layout::spacingSm();
const float listH = visRows * walRowH + std::max(0, visRows - 1) * cardGap + 4.0f * dp;
// ItemSpacing is zeroed inside the list child, so the content is exactly cards + inter-card
// gaps; a small bottom pad keeps the last card off the clip edge (no spurious scrollbar).
const float listH = visRows * walRowH + (float)std::max(0, visRows - 1) * cardGap + Layout::spacingSm();
const float ctrlRow = ImGui::GetFrameHeightWithSpacing();
const float capRow = Type().caption()->LegacySize + style.ItemSpacing.y;
@@ -96,6 +98,7 @@ public:
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
ImGui::BeginChild("##walletList", ImVec2(listW, listH), false);
ImGui::PopStyleVar();
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0)); // inter-card gaps are explicit
ImDrawList* dl = ImGui::GetWindowDrawList();
const float rowW = ImGui::GetContentRegionAvail().x;
ImFont* icoFont = Type().iconSmall();
@@ -139,10 +142,10 @@ public:
float x = rMin.x + padX;
dl->AddText(icoFont, iconSz, ImVec2(x, midY - iconSz * 0.5f),
isCurrent ? Success() : OnSurfaceMedium(), ICON_MD_ACCOUNT_BALANCE_WALLET);
x += iconSz + Layout::spacingSm();
x += iconSz + Layout::spacingMd();
// Action-button slot on the right — reserve room so text truncates before it.
const float btnW = 90.0f * dp, btnH = ImGui::GetFrameHeight();
const float btnW = 96.0f * dp, btnH = ImGui::GetFrameHeight();
const float btnX = rMax.x - padX - btnW;
const float textR = btnX - Layout::spacingMd();
@@ -191,10 +194,14 @@ public:
}
ImGui::PopID();
// Advance to the next card.
ImGui::SetCursorScreenPos(ImVec2(rMin.x, rMax.y + cardGap));
ImGui::Dummy(ImVec2(rowW, 0));
// Register the card's footprint with a Dummy (not an interactive item, so nothing
// overlaps the action button's ID) and add an explicit gap between cards (ItemSpacing
// is 0, so no double spacing; the last card has no trailing gap).
ImGui::SetCursorScreenPos(rMin);
ImGui::Dummy(ImVec2(rowW, walRowH));
if (i + 1 < s_rows.size()) ImGui::Dummy(ImVec2(rowW, cardGap));
}
ImGui::PopStyleVar(); // ItemSpacing
ImGui::EndChild();
ImGui::Dummy(ImVec2(0, Layout::spacingSm()));