feat(tui): responsive table columns — expand headers with terminal width
Replace hardcoded column widths with dynamic layout system: - Each column has short/full header and min/max width - At narrow terminals: LAT, UP%, RT, compact widths - At wide terminals: LATENCY, UPTIME, RETRIES, expanded widths - Surplus space distributed left-to-right across expandable columns - Headers switch between short/full based on actual column width Column definitions: # (4-6) TYPE (8-10) STATUS (8-10) LAT/LATENCY (5-10) UP%/UPTIME (5-8) SSL (5-7) RT/RETRIES (5-9)
This commit is contained in:
+92
-13
@@ -334,15 +334,50 @@ func fmtDuration(d time.Duration) string {
|
||||
return fmt.Sprintf("%dd", days)
|
||||
}
|
||||
|
||||
func (m Model) dynamicWidths() (nameW, sparkW int) {
|
||||
fixed := 6 + 10 + 10 + 8 + 8 + 7 + 9 // #, TYPE, STATUS, LATENCY, UPTIME, SSL, RETRY
|
||||
overhead := 30 // cell padding + borders
|
||||
avail := m.termWidth - chromePadH - 2 - fixed - overhead
|
||||
if avail < 30 {
|
||||
avail = 30
|
||||
type tableLayout struct {
|
||||
nameW, sparkW int
|
||||
headers []string
|
||||
colWidths []int
|
||||
}
|
||||
|
||||
func (m Model) computeLayout() tableLayout {
|
||||
type colDef struct {
|
||||
short string
|
||||
full string
|
||||
minWidth int
|
||||
maxWidth int
|
||||
}
|
||||
nameW = avail / 2
|
||||
sparkW = avail - nameW - 2 // -2 for spark column padding
|
||||
|
||||
cols := []colDef{
|
||||
{"#", "#", 4, 6},
|
||||
{"", "", 0, 0}, // NAME (dynamic)
|
||||
{"TYPE", "TYPE", 8, 10},
|
||||
{"STATUS", "STATUS", 8, 10},
|
||||
{"LAT", "LATENCY", 5, 10},
|
||||
{"UP%", "UPTIME", 5, 8},
|
||||
{"", "", 0, 0}, // HISTORY (dynamic)
|
||||
{"SSL", "SSL", 5, 7},
|
||||
{"RT", "RETRIES", 5, 9},
|
||||
}
|
||||
|
||||
overhead := 30
|
||||
usable := m.termWidth - chromePadH - 2 - overhead
|
||||
if usable < 80 {
|
||||
usable = 80
|
||||
}
|
||||
|
||||
fixedMin := 0
|
||||
for i, c := range cols {
|
||||
if i == 1 || i == 6 {
|
||||
continue
|
||||
}
|
||||
fixedMin += c.minWidth
|
||||
}
|
||||
|
||||
avail := usable - fixedMin
|
||||
nameW := avail / 2
|
||||
sparkW := avail - nameW - 2
|
||||
|
||||
if nameW < 13 {
|
||||
nameW = 13
|
||||
}
|
||||
@@ -355,7 +390,50 @@ func (m Model) dynamicWidths() (nameW, sparkW int) {
|
||||
if sparkW > 60 {
|
||||
sparkW = 60
|
||||
}
|
||||
return
|
||||
|
||||
surplus := usable - fixedMin - nameW - sparkW - 2
|
||||
if surplus < 0 {
|
||||
surplus = 0
|
||||
}
|
||||
|
||||
headers := make([]string, len(cols))
|
||||
widths := make([]int, len(cols))
|
||||
for i, c := range cols {
|
||||
if i == 1 {
|
||||
headers[i] = "NAME"
|
||||
widths[i] = 0
|
||||
continue
|
||||
}
|
||||
if i == 6 {
|
||||
headers[i] = "HISTORY"
|
||||
widths[i] = sparkW + 2
|
||||
continue
|
||||
}
|
||||
|
||||
w := c.minWidth
|
||||
expand := c.maxWidth - c.minWidth
|
||||
if surplus >= expand {
|
||||
w = c.maxWidth
|
||||
surplus -= expand
|
||||
} else if surplus > 0 {
|
||||
w += surplus
|
||||
surplus = 0
|
||||
}
|
||||
|
||||
if w >= len(c.full)+2 {
|
||||
headers[i] = c.full
|
||||
} else {
|
||||
headers[i] = c.short
|
||||
}
|
||||
widths[i] = w
|
||||
}
|
||||
|
||||
return tableLayout{
|
||||
nameW: nameW,
|
||||
sparkW: sparkW,
|
||||
headers: headers,
|
||||
colWidths: widths,
|
||||
}
|
||||
}
|
||||
|
||||
func (m Model) viewSitesTab() string {
|
||||
@@ -373,12 +451,13 @@ func (m Model) viewSitesTab() string {
|
||||
return "\n" + welcome
|
||||
}
|
||||
|
||||
nameW, sparkWidth := m.dynamicWidths()
|
||||
colWidths := []int{6, 0, 10, 10, 8, 8, sparkWidth + 2, 7, 9}
|
||||
layout := m.computeLayout()
|
||||
nameW := layout.nameW
|
||||
sparkWidth := layout.sparkW
|
||||
|
||||
var groupRows map[int]bool
|
||||
return m.renderTable(
|
||||
[]string{"#", "NAME", "TYPE", "STATUS", "LAT", "UPTIME", "HISTORY", "SSL", "RETRY"},
|
||||
layout.headers,
|
||||
len(m.sites),
|
||||
func(start, end int) [][]string {
|
||||
groupRows = make(map[int]bool)
|
||||
@@ -444,7 +523,7 @@ func (m Model) viewSitesTab() string {
|
||||
}
|
||||
return rows
|
||||
},
|
||||
colWidths,
|
||||
layout.colWidths,
|
||||
func(row, col int) *lipgloss.Style {
|
||||
if groupRows[row] {
|
||||
s := siteGroupStyle
|
||||
|
||||
Reference in New Issue
Block a user