fix(ui): stop sidebar badges from displacing button text
The Chat/History nav buttons centered their icon+label in a region that shrank when a badge (unread count / mining dot) was present, and the "has badge" test read the LIVE count — so the text jumped sideways the moment a count toggled (e.g. a new chat message arrived). Reserve badge clearance by whether the page CAN show a badge (constant per item), center in the full button width regardless, and cap the label with symmetric clearance so a long label still can't run under the corner badge. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -679,15 +679,18 @@ inline bool RenderSidebar(NavPage& current, float sidebarWidth, float contentHei
|
||||
ImU32 textCol = selected ? Primary() : (pageNeedsUnlock ? OnSurfaceDisabled() : OnSurfaceMedium());
|
||||
|
||||
if (showLabels) {
|
||||
// Reserve room for a badge (if this item will draw one) so the
|
||||
// label centers in the space to the left of it instead of
|
||||
// running underneath the badge circle.
|
||||
bool itemHasBadge =
|
||||
(item.page == NavPage::History && status.unconfirmedTxCount > 0) ||
|
||||
(item.page == NavPage::Mining && status.miningActive) ||
|
||||
(item.page == NavPage::Chat && status.chatUnreadCount > 0);
|
||||
// The badge is a fixed top-right corner overlay, so it must NOT move
|
||||
// the icon+label — otherwise the text jumps sideways the moment a live
|
||||
// count toggles the badge on/off. Reserve clearance from whether the
|
||||
// page CAN show a badge (constant per item), never from the current
|
||||
// count, and keep the icon+label centered in the FULL button width so
|
||||
// the text position and size stay identical with or without a badge.
|
||||
bool itemBadgeCapable =
|
||||
item.page == NavPage::History ||
|
||||
item.page == NavPage::Mining ||
|
||||
item.page == NavPage::Chat;
|
||||
float badgeReserve = 0.0f;
|
||||
if (itemHasBadge) {
|
||||
if (itemBadgeCapable) {
|
||||
bool dotOnlyReserve = (item.page == NavPage::Mining);
|
||||
float badgeRReserve = dotOnlyReserve ? badgeRadiusDot : badgeRadiusNumber;
|
||||
float badgeInsetXReserve = sde("badge-inset-x", 6.0f);
|
||||
@@ -697,14 +700,17 @@ inline bool RenderSidebar(NavPage& current, float sidebarWidth, float contentHei
|
||||
ImFont* font = selected ? Type().subtitle2() : Type().body2();
|
||||
float lblFsz = ScaledFontSize(font);
|
||||
float btnW = indMax.x - indMin.x;
|
||||
float maxLabelW = btnW - iconS * 2.0f - iconLabelGap - Layout::spacingXs() * 2 - badgeReserve;
|
||||
// Clearance is symmetric (2x) because the group stays centered in the
|
||||
// full width: reserving on both sides keeps the label's right edge clear
|
||||
// of the right-side corner badge without shifting the center off-axis.
|
||||
float maxLabelW = btnW - iconS * 2.0f - iconLabelGap - Layout::spacingXs() * 2 - badgeReserve * 2.0f;
|
||||
ImVec2 labelSz = font->CalcTextSizeA(lblFsz, 1000.0f, 0.0f, NavLabel(item));
|
||||
if (labelSz.x > maxLabelW && maxLabelW > 0) {
|
||||
lblFsz *= maxLabelW / labelSz.x;
|
||||
labelSz = font->CalcTextSizeA(lblFsz, 1000.0f, 0.0f, NavLabel(item));
|
||||
}
|
||||
float totalW = iconS * 2.0f + iconLabelGap + labelSz.x;
|
||||
float btnCX = (indMin.x + indMax.x - badgeReserve) * 0.5f;
|
||||
float btnCX = (indMin.x + indMax.x) * 0.5f;
|
||||
float startX = btnCX - totalW * 0.5f;
|
||||
|
||||
DrawNavIcon(dl, item.page, startX + iconS, iconCY, iconS, textCol);
|
||||
|
||||
Reference in New Issue
Block a user