package detail
import (
"strings"
"github.com/charmbracelet/lipgloss"
"mercemay.top/httptap/internal/tui/theme"
)
// Tabs renders a horizontal row of tab labels with one active.
type Tabs struct {
pal theme.Palette
labels []string
active lipgloss.Style
idle lipgloss.Style
gap lipgloss.Style
}
// NewTabs constructs a Tabs model with the supplied labels.
func NewTabs(pal theme.Palette, labels []string) Tabs {
return Tabs{
pal: pal,
labels: labels,
active: lipgloss.NewStyle().
Foreground(pal.HighlightFG).
Background(pal.HighlightBG).
Bold(true).
Padding(0, 2),
idle: lipgloss.NewStyle().
Foreground(pal.Dim).
Padding(0, 2),
gap: lipgloss.NewStyle().
Foreground(pal.Dim).
Render("│"),
}
}
// Labels returns the label strings.
func (t Tabs) Labels() []string { return t.labels }
// Render draws the tab strip padded or truncated to width.
func (t Tabs) Render(active, width int) string {
cells := make([]string, 0, len(t.labels))
for i, label := range t.labels {
if i == active {
cells = append(cells, t.active.Render(label))
} else {
cells = append(cells, t.idle.Render(label))
}
}
row := strings.Join(cells, t.gap)
if width <= 0 {
return row
}
if lipgloss.Width(row) > width {
return row[:width]
}
return row + strings.Repeat(" ", width-lipgloss.Width(row))
}
// Next returns the next active index; used by detail.Update.
func (t Tabs) Next(active int) int {
return (active + 1) % len(t.labels)
}
// Prev is the mirror of Next.
func (t Tabs) Prev(active int) int {
return (active - 1 + len(t.labels)) % len(t.labels)
}