feat(ui): settings polish — button retune, daemon card, RPC 2-row, chat preview

Settings tabs brought closer to the approved mockup:
- ActionButton/renderCardButton retune (settings-scoped): 7px radius, 9px
  padX, Primary → accent-outline chip, Secondary/card buttons more defined.
- Daemon-binary card: compact status right-aligned on the DAEMON BINARY
  heading (Up to date / Version differs / Not installed), filled/rounded
  status box, neutral danger divider (was alarming red), roomier spacing.
- RPC Connection: two-row column-aligned layout (Host | Port, then
  Username | Password) so the password no longer clips off the card edge.
- Chat settings tab: live conversation preview below the Appearance /
  Messaging cards; "Focus input on open" checkbox reflowed onto the console
  color-toggle row.
- Debug Options: "Current theme only" toggle restricts either screenshot
  sweep to the active theme instead of cycling every skin.
- Tabs fill the full content width (content-max-width cap disabled) and the
  sidebar nav panel centers within the true visible area.
- i18n: new keys for the above (untranslated keys fall back to English).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-20 16:59:03 -05:00
parent b37d3d97b6
commit d0bd55b9c1
19 changed files with 1082 additions and 990 deletions

View File

@@ -1795,32 +1795,21 @@ void App::render()
sbStatus.unconfirmedTxCount = static_cast<int>(unconfirmedTxids.size());
}
// Sidebar margins from ui.toml schema (DPI-scaled like all sidebar values)
const float sbMarginTop = sbde("margin-top", 0.0f);
const float sbMarginBottom = sbde("margin-bottom", 0.0f);
const float sbMinHeight = sbde("min-height", 360.0f);
// Sidebar minimum height from ui.toml schema (DPI-scaled).
const float sbMinHeight = sbde("min-height", 360.0f);
// Ensure sidebar is tall enough to fit all buttons — shrink margins if needed
float sidebarH = contentH - sbMarginTop - sbMarginBottom;
float effectiveMarginTop = sbMarginTop;
if (sidebarH < sbMinHeight) {
float available = contentH - sbMinHeight;
if (available > 0.0f) {
float ratio = available / (sbMarginTop + sbMarginBottom);
effectiveMarginTop = sbMarginTop * ratio;
} else {
effectiveMarginTop = 0.0f;
}
sidebarH = std::max(contentH - effectiveMarginTop, sbMinHeight);
}
// Sidebar navigation
// Save cursor Y before applying sidebar margin so the content area
// (placed via SameLine) starts at the original row position, not the
// margin-shifted one.
// Save cursor Y before the sidebar so the content area (restored below) starts at the original row.
float preSidebarCursorY = ImGui::GetCursorPosY();
if (effectiveMarginTop > 0.0f)
ImGui::SetCursorPosY(preSidebarCursorY + effectiveMarginTop);
// Size the sidebar to span from its own top down to the status-bar top, so the nav panel centers
// within the TRUE visible area (equal top/bottom gaps). Do NOT derive it from contentH (inset by the
// content-area's edge-fade margins) and do NOT apply the legacy sidebar margin-top/-bottom (they are
// asymmetric, -12 / +40, and pushed the panel upward). Window-local reference (matches how the status
// bar is positioned — GetWindowPos/GetWindowSize, not GetMainViewport) so it is correct on every platform.
float sbWindowBottom = ImGui::GetWindowPos().y + ImGui::GetWindowSize().y;
float sbStatusTopY = sbWindowBottom - statusBarH - mainPadBot;
float sbChildTopY = ImGui::GetCursorScreenPos().y;
float sidebarH = std::max(sbMinHeight, sbStatusTopY - sbChildTopY);
bool prevCollapsed = sidebar_collapsed_;
{
PERF_SCOPE("Render.Sidebar");