tabs.go

 1package tabs
 2
 3import (
 4	"strings"
 5
 6	tea "github.com/charmbracelet/bubbletea"
 7	"github.com/charmbracelet/soft-serve/ui/common"
 8)
 9
10// SelectTabMsg is a message that contains the index of the tab to select.
11type SelectTabMsg int
12
13// ActiveTabMsg is a message that contains the index of the current active tab.
14type ActiveTabMsg int
15
16// Tabs is bubbletea component that displays a list of tabs.
17type Tabs struct {
18	common    common.Common
19	tabs      []string
20	activeTab int
21}
22
23// New creates a new Tabs component.
24func New(c common.Common, tabs []string) *Tabs {
25	r := &Tabs{
26		common:    c,
27		tabs:      tabs,
28		activeTab: 0,
29	}
30	return r
31}
32
33// SetSize implements common.Component.
34func (t *Tabs) SetSize(width, height int) {
35	t.common.SetSize(width, height)
36}
37
38// Init implements tea.Model.
39func (t *Tabs) Init() tea.Cmd {
40	t.activeTab = 0
41	return nil
42}
43
44// Update implements tea.Model.
45func (t *Tabs) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
46	cmds := make([]tea.Cmd, 0)
47	switch msg := msg.(type) {
48	case tea.KeyMsg:
49		switch msg.String() {
50		case "tab":
51			t.activeTab = (t.activeTab + 1) % len(t.tabs)
52			cmds = append(cmds, t.activeTabCmd)
53		case "shift+tab":
54			t.activeTab = (t.activeTab - 1 + len(t.tabs)) % len(t.tabs)
55			cmds = append(cmds, t.activeTabCmd)
56		}
57	case SelectTabMsg:
58		tab := int(msg)
59		if tab >= 0 && tab < len(t.tabs) {
60			t.activeTab = int(msg)
61		}
62	}
63	return t, tea.Batch(cmds...)
64}
65
66// View implements tea.Model.
67func (t *Tabs) View() string {
68	s := strings.Builder{}
69	sep := t.common.Styles.TabSeparator
70	for i, tab := range t.tabs {
71		style := t.common.Styles.TabInactive.Copy()
72		if i == t.activeTab {
73			style = t.common.Styles.TabActive.Copy()
74		}
75		s.WriteString(style.Render(tab))
76		if i != len(t.tabs)-1 {
77			s.WriteString(sep.String())
78		}
79	}
80	return s.String()
81}
82
83func (t *Tabs) activeTabCmd() tea.Msg {
84	return ActiveTabMsg(t.activeTab)
85}
86
87// SelectTabCmd is a bubbletea command that selects the tab at the given index.
88func SelectTabCmd(tab int) tea.Cmd {
89	return func() tea.Msg {
90		return SelectTabMsg(tab)
91	}
92}