twink/tui/header.go

155 lines
3 KiB
Go
Raw Normal View History

2025-12-06 11:01:11 +01:00
package tui
import (
"fmt"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
)
type (
HeaderModel struct{
2025-12-07 11:42:57 +01:00
Size Size
2025-12-06 11:01:11 +01:00
Tabs []HeaderTabModel
}
HeaderTabModel struct{
2025-12-07 11:42:57 +01:00
Size Size
Active bool
2025-12-06 11:01:11 +01:00
Name string
2025-12-07 11:42:57 +01:00
Key rune
2025-12-06 11:01:11 +01:00
Unread int
}
)
func NewHeader() HeaderModel {
return HeaderModel{
Tabs: []HeaderTabModel {
2025-12-07 11:42:57 +01:00
NewHeaderTab("Home", 'H', 10, true),
NewHeaderTab("Notifications", 'N', 3, false),
NewHeaderTab("Lists", 'L', 5, false),
NewHeaderTab("Private", 'P', 0, false),
2025-12-06 11:01:11 +01:00
},
}
}
2025-12-07 11:42:57 +01:00
func NewHeaderTab(name string, key rune, unread int, current bool) HeaderTabModel {
return HeaderTabModel{ Name: name, Key: key, Unread: unread, Active: current }
2025-12-06 11:01:11 +01:00
}
var (
activeTabBorder = lipgloss.Border{
Top: "─",
Bottom: " ",
Left: "│",
Right: "│",
TopLeft: "╭",
TopRight: "╮",
BottomLeft: "┘",
BottomRight: "└",
}
tabBorder = lipgloss.Border{
Top: "─",
Bottom: "─",
Left: "│",
Right: "│",
TopLeft: "╭",
TopRight: "╮",
BottomLeft: "┴",
BottomRight: "┴",
}
headerTabStyle = lipgloss.NewStyle().
2025-12-07 11:42:57 +01:00
Padding(0, 1).
2025-12-06 11:01:11 +01:00
Border(tabBorder, true)
activeHeaderTabStyle = headerTabStyle.
Border(activeTabBorder, true)
)
func (m HeaderModel) Init() tea.Cmd {
return nil
}
func (m HeaderModel) Update(msg tea.Msg) (HeaderModel, tea.Cmd) {
var cmd tea.Cmd
2025-12-07 11:42:57 +01:00
switch msg.(type) {
case SwitchHomeScreenMsg:
m.SetActive(0)
case SwitchNotificationScreenMsg:
m.SetActive(1)
2025-12-06 11:01:11 +01:00
}
return m, cmd
}
2025-12-07 11:42:57 +01:00
func (m *HeaderModel) SetActive(tabIndex int) {
for i := range m.Tabs {
m.Tabs[i].Active = i == tabIndex
}
}
func (m *HeaderModel) SetWidth(width int) {
tabWidth := width / len(m.Tabs)
var maxTabHeight int
for i := range m.Tabs {
m.Tabs[i].SetSize(tabWidth)
maxTabHeight = max(maxTabHeight, m.Tabs[i].Size.Height)
}
m.Size = Size{
Width: width,
Height: 3+maxTabHeight,
}
}
2025-12-06 11:01:11 +01:00
func (m HeaderModel) View() string {
header := lipgloss.NewStyle().
Padding(1, 0).
Align(lipgloss.Center).
2025-12-07 11:42:57 +01:00
Width(m.Size.Width)
2025-12-06 11:01:11 +01:00
renderedTabs := make([]string, len(m.Tabs))
for i, tab := range m.Tabs {
renderedTabs[i] = tab.View()
}
2025-12-07 11:42:57 +01:00
joinedTabs := lipgloss.JoinHorizontal(lipgloss.Bottom, renderedTabs...)
2025-12-06 11:01:11 +01:00
2025-12-07 11:42:57 +01:00
return header.Render(joinedTabs)
2025-12-06 11:01:11 +01:00
}
func (m HeaderTabModel) Init() tea.Cmd {
return nil
}
2025-12-07 11:42:57 +01:00
func (m HeaderTabModel) Update(msg tea.Msg) (HeaderTabModel, tea.Cmd) {
2025-12-06 11:01:11 +01:00
var cmd tea.Cmd
return m, cmd
}
2025-12-07 11:42:57 +01:00
func (m *HeaderTabModel) SetSize(width int) {
m.Size = Size{
Width: width,
Height: 1,
}
}
2025-12-06 11:01:11 +01:00
func (m HeaderTabModel) View() string {
2025-12-07 11:42:57 +01:00
contentWidth := m.Size.Width - 4
content := fmt.Sprintf("[%c] %s - %d", m.Key, m.Name, m.Unread)
if len(content) > contentWidth {
content = fmt.Sprintf("[%c] %d", m.Key, m.Unread)
if len(content) > contentWidth {
content = fmt.Sprintf("[%c]", m.Key)
}
}
content = lipgloss.PlaceHorizontal(contentWidth, lipgloss.Center, content)
2025-12-06 11:01:11 +01:00
2025-12-07 11:42:57 +01:00
if m.Active {
return activeHeaderTabStyle.Render(content)
2025-12-06 11:01:11 +01:00
}
2025-12-07 11:42:57 +01:00
return headerTabStyle.Render(content)
2025-12-06 11:01:11 +01:00
}