feat(tui): styled section headers with trailing rules in detail panel
Section labels (STATE CHANGES, LATENCY, RESPONSE TIME DISTRIBUTION, PROBE RESULTS) now render in bold accent color with a trailing ─── rule that fills the width. Two-column info block separated by a full divider below. Creates clear visual boundaries between sections.
This commit is contained in:
@@ -47,6 +47,15 @@ func (m Model) viewDetailPanel() string {
|
|||||||
return fmt.Sprintf(" %-16s %s", m.st.subtleStyle.Render(label), value)
|
return fmt.Sprintf(" %-16s %s", m.st.subtleStyle.Render(label), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
divW := totalW - 4
|
||||||
|
if divW < 20 {
|
||||||
|
divW = 20
|
||||||
|
}
|
||||||
|
sectionDiv := m.st.subtleStyle.Render(strings.Repeat("─", divW))
|
||||||
|
sectionHead := func(title string) string {
|
||||||
|
return m.st.titleStyle.Render(" "+title) + " " + m.st.subtleStyle.Render(strings.Repeat("─", divW-len(title)-3))
|
||||||
|
}
|
||||||
|
|
||||||
// Left column: status + endpoint
|
// Left column: status + endpoint
|
||||||
var left []string
|
var left []string
|
||||||
left = append(left, row("Status", m.fmtStatus(site.Status, site.Paused, m.isMonitorInMaintenance(site.ID))))
|
left = append(left, row("Status", m.fmtStatus(site.Status, site.Paused, m.isMonitorInMaintenance(site.ID))))
|
||||||
@@ -69,7 +78,7 @@ func (m Model) viewDetailPanel() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
left = append(left, "")
|
left = append(left, "")
|
||||||
left = append(left, m.st.subtleStyle.Render(" ENDPOINT"))
|
left = append(left, m.st.titleStyle.Render(" ENDPOINT"))
|
||||||
left = append(left, row("Type", site.Type))
|
left = append(left, row("Type", site.Type))
|
||||||
if site.URL != "" {
|
if site.URL != "" {
|
||||||
left = append(left, row("URL", limitStr(site.URL, colW-19)))
|
left = append(left, row("URL", limitStr(site.URL, colW-19)))
|
||||||
@@ -95,7 +104,7 @@ func (m Model) viewDetailPanel() string {
|
|||||||
|
|
||||||
if site.Type == "http" {
|
if site.Type == "http" {
|
||||||
right = append(right, "")
|
right = append(right, "")
|
||||||
right = append(right, m.st.subtleStyle.Render(" HTTP"))
|
right = append(right, m.st.titleStyle.Render(" HTTP"))
|
||||||
codes := site.AcceptedCodes
|
codes := site.AcceptedCodes
|
||||||
if codes == "" {
|
if codes == "" {
|
||||||
codes = "200-299"
|
codes = "200-299"
|
||||||
@@ -122,6 +131,7 @@ func (m Model) viewDetailPanel() string {
|
|||||||
leftCol := lipgloss.NewStyle().Width(colW).Render(strings.Join(left, "\n"))
|
leftCol := lipgloss.NewStyle().Width(colW).Render(strings.Join(left, "\n"))
|
||||||
rightCol := lipgloss.NewStyle().Width(colW).Render(strings.Join(right, "\n"))
|
rightCol := lipgloss.NewStyle().Width(colW).Render(strings.Join(right, "\n"))
|
||||||
b.WriteString(lipgloss.JoinHorizontal(lipgloss.Top, leftCol, rightCol) + "\n")
|
b.WriteString(lipgloss.JoinHorizontal(lipgloss.Top, leftCol, rightCol) + "\n")
|
||||||
|
b.WriteString(sectionDiv + "\n")
|
||||||
|
|
||||||
// Connection chain (full width, only on errors)
|
// Connection chain (full width, only on errors)
|
||||||
if (site.Status == models.StatusDown || site.Status == models.StatusSSLExp) && site.LastError != "" {
|
if (site.Status == models.StatusDown || site.Status == models.StatusSSLExp) && site.LastError != "" {
|
||||||
@@ -175,7 +185,7 @@ func (m Model) viewDetailPanel() string {
|
|||||||
nodeIDs = append(nodeIDs, id)
|
nodeIDs = append(nodeIDs, id)
|
||||||
}
|
}
|
||||||
sort.Strings(nodeIDs)
|
sort.Strings(nodeIDs)
|
||||||
b.WriteString("\n" + m.st.subtleStyle.Render(" PROBE RESULTS") + "\n")
|
b.WriteString("\n" + sectionHead("PROBE RESULTS") + "\n")
|
||||||
for _, nodeID := range nodeIDs {
|
for _, nodeID := range nodeIDs {
|
||||||
result := probeResults[nodeID]
|
result := probeResults[nodeID]
|
||||||
status := m.st.specialStyle.Render("UP")
|
status := m.st.specialStyle.Render("UP")
|
||||||
@@ -198,7 +208,7 @@ func (m Model) viewDetailPanel() string {
|
|||||||
stateChanges = m.detailChanges
|
stateChanges = m.detailChanges
|
||||||
}
|
}
|
||||||
if len(stateChanges) > 0 {
|
if len(stateChanges) > 0 {
|
||||||
b.WriteString("\n" + m.st.subtleStyle.Render(" STATE CHANGES") + "\n")
|
b.WriteString("\n" + sectionHead("STATE CHANGES") + "\n")
|
||||||
for i, sc := range stateChanges {
|
for i, sc := range stateChanges {
|
||||||
from := m.fmtStatusWord(string(sc.FromStatus))
|
from := m.fmtStatusWord(string(sc.FromStatus))
|
||||||
to := m.fmtStatusWord(string(sc.ToStatus))
|
to := m.fmtStatusWord(string(sc.ToStatus))
|
||||||
@@ -218,7 +228,7 @@ func (m Model) viewDetailPanel() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sparkline + stats
|
// Sparkline + stats
|
||||||
b.WriteString("\n")
|
b.WriteString("\n" + sectionHead("LATENCY") + "\n")
|
||||||
if site.Type == "push" {
|
if site.Type == "push" {
|
||||||
b.WriteString(" " + m.zones.Mark("spark-heartbeat", m.heartbeatSparkline(hist.Statuses, detailSparkWidth, nil)))
|
b.WriteString(" " + m.zones.Mark("spark-heartbeat", m.heartbeatSparkline(hist.Statuses, detailSparkWidth, nil)))
|
||||||
if len(hist.Statuses) > 0 {
|
if len(hist.Statuses) > 0 {
|
||||||
@@ -269,7 +279,7 @@ func (m Model) viewDetailPanel() string {
|
|||||||
if histW < 30 {
|
if histW < 30 {
|
||||||
histW = 30
|
histW = 30
|
||||||
}
|
}
|
||||||
b.WriteString("\n\n" + m.st.subtleStyle.Render(" RESPONSE TIME DISTRIBUTION") + "\n")
|
b.WriteString("\n" + sectionHead("RESPONSE TIME DISTRIBUTION") + "\n")
|
||||||
b.WriteString(m.latencyHistogram(hist.Latencies, hist.Statuses, histW))
|
b.WriteString(m.latencyHistogram(hist.Latencies, hist.Statuses, histW))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user