Diff
1diff --git a/tui/bubble.go b/tui/bubble.go
2index a699c89349723e923ad54e0549e1bb1fbe38ce77..392fa14c73c62091ae7db3e7d15e24ed4d21330a 100644
3--- a/tui/bubble.go
4+++ b/tui/bubble.go
5@@ -139,11 +139,10 @@ func (b *Bubble) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
6 }
7
8 func (b *Bubble) viewForBox(i int) string {
9- box := b.boxes[i]
10 isActive := i == b.activeBox
11- var s lipgloss.Style
12- switch box.(type) {
13+ switch box := b.boxes[i].(type) {
14 case *selection.Bubble:
15+ var s lipgloss.Style
16 if isActive {
17 s = menuActiveStyle
18 } else {
19@@ -155,23 +154,13 @@ func (b *Bubble) viewForBox(i int) string {
20 s.GetVerticalFrameSize() -
21 appBoxStyle.GetVerticalFrameSize() +
22 1 // TODO: figure out why we need this
23- s = s.Copy().Height(h)
24+ return s.Copy().Height(h).Render(box.View())
25 case *repo.Bubble:
26- if isActive {
27- s = contentBoxActiveStyle
28- } else {
29- s = contentBoxStyle
30- }
31- w := b.width -
32- lipgloss.Width(b.viewForBox(0)) -
33- appBoxStyle.GetHorizontalFrameSize() -
34- s.GetHorizontalFrameSize() +
35- 1 // TODO: figure out why we need this
36- s = s.Copy().Width(w)
37+ box.Active = isActive
38+ return box.View()
39 default:
40 panic(fmt.Sprintf("unknown box type %T", box))
41 }
42- return s.Render(box.View())
43 }
44
45 func (b Bubble) headerView() string {
46diff --git a/tui/bubbles/repo/bubble.go b/tui/bubbles/repo/bubble.go
47index 12d45464b8e1e83a830805910d41394f00559b32..ea518adaa0942eb088399eb74504a242527c122b 100644
48--- a/tui/bubbles/repo/bubble.go
49+++ b/tui/bubbles/repo/bubble.go
50@@ -8,6 +8,7 @@ import (
51 "github.com/charmbracelet/bubbles/viewport"
52 tea "github.com/charmbracelet/bubbletea"
53 "github.com/charmbracelet/glamour"
54+ "github.com/charmbracelet/lipgloss"
55 "github.com/muesli/reflow/wordwrap"
56 "github.com/muesli/reflow/wrap"
57 )
58@@ -19,16 +20,21 @@ type ErrMsg struct {
59 }
60
61 type Bubble struct {
62- templateObject interface{}
63- repoSource *git.RepoSource
64- name string
65- repo *git.Repo
66- readmeViewport *ViewportBubble
67- readme string
68- height int
69- heightMargin int
70- width int
71- widthMargin int
72+ templateObject interface{}
73+ repoSource *git.RepoSource
74+ name string
75+ repo *git.Repo
76+ readmeViewport *ViewportBubble
77+ readme string
78+ height int
79+ heightMargin int
80+ width int
81+ widthMargin int
82+ Active bool
83+ TitleStyle lipgloss.Style
84+ NoteStyle lipgloss.Style
85+ BodyStyle lipgloss.Style
86+ ActiveBorderColor lipgloss.Color
87 }
88
89 func NewBubble(rs *git.RepoSource, name string, width, wm, height, hm int, tmp interface{}) *Bubble {
90@@ -81,8 +87,31 @@ func (b *Bubble) GotoTop() {
91 b.readmeViewport.Viewport.GotoTop()
92 }
93
94+func (b Bubble) headerView() string {
95+ ts := b.TitleStyle
96+ ns := b.NoteStyle
97+ if b.Active {
98+ ts = ts.Copy().BorderForeground(b.ActiveBorderColor)
99+ ns = ns.Copy().BorderForeground(b.ActiveBorderColor)
100+ }
101+ title := ts.Render(b.name)
102+ note := ns.
103+ Width(b.width - b.widthMargin - lipgloss.Width(title)).
104+ Render("git clone ssh://...")
105+ return lipgloss.JoinHorizontal(lipgloss.Top, title, note)
106+}
107+
108 func (b *Bubble) View() string {
109- return b.readmeViewport.View()
110+ header := b.headerView()
111+ bs := b.BodyStyle.Copy()
112+ if b.Active {
113+ bs = bs.BorderForeground(b.ActiveBorderColor)
114+ }
115+ body := bs.
116+ Width(b.width - b.widthMargin - b.BodyStyle.GetVerticalFrameSize()).
117+ Height(b.height - b.heightMargin - lipgloss.Height(header)).
118+ Render(b.readmeViewport.View())
119+ return header + body
120 }
121
122 func (b *Bubble) setupCmd() tea.Msg {
123diff --git a/tui/commands.go b/tui/commands.go
124index b8db6e08c3cc992a51698c9c008226389c272d42..1c126872ca3cfa4867619d3d0060c29ad4fbd541 100644
125--- a/tui/commands.go
126+++ b/tui/commands.go
127@@ -54,8 +54,13 @@ func (b *Bubble) setupCmd() tea.Msg {
128 var heightMargin = lipgloss.Height(b.headerView()) +
129 lipgloss.Height(b.footerView()) +
130 contentBoxStyle.GetVerticalFrameSize() +
131- appBoxStyle.GetVerticalMargins()
132+ appBoxStyle.GetVerticalMargins() +
133+ 3 // TODO: make this dynamic (this is the height of the repo info)
134 rb := repo.NewBubble(b.repoSource, me.Repo, width, boxLeftWidth, b.height, heightMargin, tmplConfig)
135+ rb.TitleStyle = contentBoxTitleStyle
136+ rb.NoteStyle = contentBoxNoteStyle
137+ rb.BodyStyle = contentBoxStyle
138+ rb.ActiveBorderColor = activeBorderColor
139 initCmd := rb.Init()
140 msg := initCmd()
141 switch msg := msg.(type) {
142diff --git a/tui/style.go b/tui/style.go
143index cd0f807a323eed3442a36cac67cffc7a0b911cde..7d25bfbb8b5e6076447270d834a2d341b2b541c8 100644
144--- a/tui/style.go
145+++ b/tui/style.go
146@@ -7,6 +7,39 @@ import (
147 var activeBorderColor = lipgloss.Color("62")
148 var inactiveBorderColor = lipgloss.Color("236")
149
150+var viewportTitleBorder = lipgloss.Border{
151+ Top: "─",
152+ Bottom: "─",
153+ Left: "│",
154+ Right: "│",
155+ TopLeft: "╭",
156+ TopRight: "┬",
157+ BottomLeft: "├",
158+ BottomRight: "┴",
159+}
160+
161+var viewportNoteBorder = lipgloss.Border{
162+ Top: "─",
163+ Bottom: "─",
164+ Left: "",
165+ Right: "│",
166+ TopLeft: "",
167+ TopRight: "╮",
168+ BottomLeft: "",
169+ BottomRight: "┤",
170+}
171+
172+var viewportBodyBorder = lipgloss.Border{
173+ Top: "",
174+ Bottom: "─",
175+ Left: "│",
176+ Right: "│",
177+ TopLeft: "",
178+ TopRight: "",
179+ BottomLeft: "╰",
180+ BottomRight: "╯",
181+}
182+
183 var appBoxStyle = lipgloss.NewStyle().
184 Margin(1, 2)
185
186@@ -31,15 +64,20 @@ var menuCursor = lipgloss.NewStyle().
187 Foreground(lipgloss.Color("213")).
188 SetString(">")
189
190-var contentBoxStyle = lipgloss.NewStyle().
191- BorderStyle(lipgloss.RoundedBorder()).
192+var contentBoxTitleStyle = lipgloss.NewStyle().
193+ Border(viewportTitleBorder).
194 BorderForeground(inactiveBorderColor).
195- PaddingRight(1).
196- MarginBottom(1)
197+ Padding(0, 2)
198
199-var contentBoxActiveStyle = contentBoxStyle.Copy().
200- BorderStyle(lipgloss.RoundedBorder()).
201- BorderForeground(activeBorderColor)
202+var contentBoxNoteStyle = lipgloss.NewStyle().
203+ Border(viewportNoteBorder, true, true, true, false).
204+ BorderForeground(inactiveBorderColor).
205+ Padding(0, 2)
206+
207+var contentBoxStyle = lipgloss.NewStyle().
208+ BorderStyle(viewportBodyBorder).
209+ BorderForeground(inactiveBorderColor).
210+ PaddingRight(1)
211
212 var menuItemStyle = lipgloss.NewStyle().
213 Foreground(lipgloss.Color("252")).
214@@ -49,7 +87,8 @@ var selectedMenuItemStyle = lipgloss.NewStyle().
215 Foreground(lipgloss.Color("207")).
216 PaddingLeft(1)
217
218-var footerStyle = lipgloss.NewStyle()
219+var footerStyle = lipgloss.NewStyle().
220+ MarginTop(1)
221
222 var helpKeyStyle = lipgloss.NewStyle().
223 Foreground(lipgloss.Color("241"))