From 69a8e0f7bae0e72ffb5bae29e8882f156eab71f0 Mon Sep 17 00:00:00 2001 From: Tyler Koenig Date: Fri, 5 Jun 2026 17:14:07 -0400 Subject: [PATCH] =?UTF-8?q?polish(tui):=20overhaul=20tab=20bar=20=E2=80=94?= =?UTF-8?q?=20consistent=20counts,=20active=20highlight,=20colored=20alert?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #89 --- internal/tui/tui.go | 2 +- internal/tui/view_dashboard.go | 57 ++++++++++++++++------------------ 2 files changed, 28 insertions(+), 31 deletions(-) diff --git a/internal/tui/tui.go b/internal/tui/tui.go index bc0b3af..c964d27 100644 --- a/internal/tui/tui.go +++ b/internal/tui/tui.go @@ -43,7 +43,7 @@ func applyTheme(t Theme) { sparkDanger = string(t.Danger) titleStyle = lipgloss.NewStyle().Foreground(t.Accent).Bold(true) - activeTab = lipgloss.NewStyle().Border(lipgloss.NormalBorder(), false, false, true, false).BorderForeground(t.Accent).Foreground(t.Accent).Bold(true).Padding(0, 1) + activeTab = lipgloss.NewStyle().Background(t.Surface).Foreground(t.Accent).Bold(true).Padding(0, 1) inactiveTab = lipgloss.NewStyle().Padding(0, 1).Foreground(t.Muted) tableHeaderStyle = lipgloss.NewStyle().Foreground(t.Accent).Bold(true).Padding(0, 1) diff --git a/internal/tui/view_dashboard.go b/internal/tui/view_dashboard.go index 5fa9a2b..b049faf 100644 --- a/internal/tui/view_dashboard.go +++ b/internal/tui/view_dashboard.go @@ -190,45 +190,42 @@ func (m Model) viewDashboard() string { return outerPad.Render(lipgloss.JoinVertical(lipgloss.Top, header, paddedContent, footer)) } +type tabEntry struct { + name string + count int + warn int +} + func (m Model) renderTabBar(stats dashboardStats) string { - var sitesLabel string - if stats.downCount > 0 { - sitesLabel = fmt.Sprintf("Sites (%d↓)", stats.downCount) - } else if stats.lateCount > 0 { - sitesLabel = fmt.Sprintf("Sites (%d⚠)", stats.lateCount) - } else if stats.totalMonitors > 0 { - sitesLabel = fmt.Sprintf("Sites (%d)", stats.totalMonitors) - } else { - sitesLabel = "Sites" + tabs := []tabEntry{ + {"Sites", stats.totalMonitors, stats.downCount + stats.lateCount}, + {"Alerts", len(m.alerts), 0}, + {"Logs", 0, 0}, + {"Nodes", len(m.nodes), stats.offlineNodes}, + {"Maint", len(m.maintenanceWindows), stats.activeMaint}, } - - var nodesLabel string - if stats.offlineNodes > 0 { - nodesLabel = fmt.Sprintf("Nodes (%d!)", stats.offlineNodes) - } else if len(m.nodes) > 0 { - nodesLabel = fmt.Sprintf("Nodes (%d)", len(m.nodes)) - } else { - nodesLabel = "Nodes" - } - - var maintLabel string - if stats.activeMaint > 0 { - maintLabel = fmt.Sprintf("Maint (%d)", stats.activeMaint) - } else { - maintLabel = "Maint" - } - - tabs := []string{sitesLabel, "Alerts", "Logs", nodesLabel, maintLabel} if m.isAdmin { - tabs = append(tabs, "Users") + tabs = append(tabs, tabEntry{"Users", len(m.users), 0}) } + + countStyle := lipgloss.NewStyle().Foreground(m.theme.Muted) + var renderedTabs []string for i, t := range tabs { + label := t.name + if t.count > 0 { + badge := countStyle.Render(fmt.Sprintf(" %d", t.count)) + if t.warn > 0 { + badge = dangerStyle.Render(fmt.Sprintf(" %d", t.warn)) + } + label += badge + } + var rendered string if i == m.currentTab { - rendered = activeTab.Render(t) + rendered = activeTab.Render(label) } else { - rendered = inactiveTab.Render(t) + rendered = inactiveTab.Render(label) } renderedTabs = append(renderedTabs, m.zones.Mark(fmt.Sprintf("tab-%d", i), rendered)) }