Add title/clone info to repo pane

Christian Rocha created

Change summary

tui/bubble.go              | 21 +++-----------
tui/bubbles/repo/bubble.go | 51 +++++++++++++++++++++++++++++--------
tui/commands.go            |  7 ++++
tui/style.go               | 55 ++++++++++++++++++++++++++++++++++-----
4 files changed, 98 insertions(+), 36 deletions(-)

Detailed changes

tui/bubble.go 🔗

@@ -139,11 +139,10 @@ func (b *Bubble) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 }
 
 func (b *Bubble) viewForBox(i int) string {
-	box := b.boxes[i]
 	isActive := i == b.activeBox
-	var s lipgloss.Style
-	switch box.(type) {
+	switch box := b.boxes[i].(type) {
 	case *selection.Bubble:
+		var s lipgloss.Style
 		if isActive {
 			s = menuActiveStyle
 		} else {
@@ -155,23 +154,13 @@ func (b *Bubble) viewForBox(i int) string {
 			s.GetVerticalFrameSize() -
 			appBoxStyle.GetVerticalFrameSize() +
 			1 // TODO: figure out why we need this
-		s = s.Copy().Height(h)
+		return s.Copy().Height(h).Render(box.View())
 	case *repo.Bubble:
-		if isActive {
-			s = contentBoxActiveStyle
-		} else {
-			s = contentBoxStyle
-		}
-		w := b.width -
-			lipgloss.Width(b.viewForBox(0)) -
-			appBoxStyle.GetHorizontalFrameSize() -
-			s.GetHorizontalFrameSize() +
-			1 // TODO: figure out why we need this
-		s = s.Copy().Width(w)
+		box.Active = isActive
+		return box.View()
 	default:
 		panic(fmt.Sprintf("unknown box type %T", box))
 	}
-	return s.Render(box.View())
 }
 
 func (b Bubble) headerView() string {

tui/bubbles/repo/bubble.go 🔗

@@ -8,6 +8,7 @@ import (
 	"github.com/charmbracelet/bubbles/viewport"
 	tea "github.com/charmbracelet/bubbletea"
 	"github.com/charmbracelet/glamour"
+	"github.com/charmbracelet/lipgloss"
 	"github.com/muesli/reflow/wordwrap"
 	"github.com/muesli/reflow/wrap"
 )
@@ -19,16 +20,21 @@ type ErrMsg struct {
 }
 
 type Bubble struct {
-	templateObject interface{}
-	repoSource     *git.RepoSource
-	name           string
-	repo           *git.Repo
-	readmeViewport *ViewportBubble
-	readme         string
-	height         int
-	heightMargin   int
-	width          int
-	widthMargin    int
+	templateObject    interface{}
+	repoSource        *git.RepoSource
+	name              string
+	repo              *git.Repo
+	readmeViewport    *ViewportBubble
+	readme            string
+	height            int
+	heightMargin      int
+	width             int
+	widthMargin       int
+	Active            bool
+	TitleStyle        lipgloss.Style
+	NoteStyle         lipgloss.Style
+	BodyStyle         lipgloss.Style
+	ActiveBorderColor lipgloss.Color
 }
 
 func NewBubble(rs *git.RepoSource, name string, width, wm, height, hm int, tmp interface{}) *Bubble {
@@ -81,8 +87,31 @@ func (b *Bubble) GotoTop() {
 	b.readmeViewport.Viewport.GotoTop()
 }
 
+func (b Bubble) headerView() string {
+	ts := b.TitleStyle
+	ns := b.NoteStyle
+	if b.Active {
+		ts = ts.Copy().BorderForeground(b.ActiveBorderColor)
+		ns = ns.Copy().BorderForeground(b.ActiveBorderColor)
+	}
+	title := ts.Render(b.name)
+	note := ns.
+		Width(b.width - b.widthMargin - lipgloss.Width(title)).
+		Render("git clone ssh://...")
+	return lipgloss.JoinHorizontal(lipgloss.Top, title, note)
+}
+
 func (b *Bubble) View() string {
-	return b.readmeViewport.View()
+	header := b.headerView()
+	bs := b.BodyStyle.Copy()
+	if b.Active {
+		bs = bs.BorderForeground(b.ActiveBorderColor)
+	}
+	body := bs.
+		Width(b.width - b.widthMargin - b.BodyStyle.GetVerticalFrameSize()).
+		Height(b.height - b.heightMargin - lipgloss.Height(header)).
+		Render(b.readmeViewport.View())
+	return header + body
 }
 
 func (b *Bubble) setupCmd() tea.Msg {

tui/commands.go 🔗

@@ -54,8 +54,13 @@ func (b *Bubble) setupCmd() tea.Msg {
 		var heightMargin = lipgloss.Height(b.headerView()) +
 			lipgloss.Height(b.footerView()) +
 			contentBoxStyle.GetVerticalFrameSize() +
-			appBoxStyle.GetVerticalMargins()
+			appBoxStyle.GetVerticalMargins() +
+			3 // TODO: make this dynamic (this is the height of the repo info)
 		rb := repo.NewBubble(b.repoSource, me.Repo, width, boxLeftWidth, b.height, heightMargin, tmplConfig)
+		rb.TitleStyle = contentBoxTitleStyle
+		rb.NoteStyle = contentBoxNoteStyle
+		rb.BodyStyle = contentBoxStyle
+		rb.ActiveBorderColor = activeBorderColor
 		initCmd := rb.Init()
 		msg := initCmd()
 		switch msg := msg.(type) {

tui/style.go 🔗

@@ -7,6 +7,39 @@ import (
 var activeBorderColor = lipgloss.Color("62")
 var inactiveBorderColor = lipgloss.Color("236")
 
+var viewportTitleBorder = lipgloss.Border{
+	Top:         "─",
+	Bottom:      "─",
+	Left:        "│",
+	Right:       "│",
+	TopLeft:     "╭",
+	TopRight:    "┬",
+	BottomLeft:  "├",
+	BottomRight: "┴",
+}
+
+var viewportNoteBorder = lipgloss.Border{
+	Top:         "─",
+	Bottom:      "─",
+	Left:        "",
+	Right:       "│",
+	TopLeft:     "",
+	TopRight:    "╮",
+	BottomLeft:  "",
+	BottomRight: "┤",
+}
+
+var viewportBodyBorder = lipgloss.Border{
+	Top:         "",
+	Bottom:      "─",
+	Left:        "│",
+	Right:       "│",
+	TopLeft:     "",
+	TopRight:    "",
+	BottomLeft:  "╰",
+	BottomRight: "╯",
+}
+
 var appBoxStyle = lipgloss.NewStyle().
 	Margin(1, 2)
 
@@ -31,15 +64,20 @@ var menuCursor = lipgloss.NewStyle().
 	Foreground(lipgloss.Color("213")).
 	SetString(">")
 
-var contentBoxStyle = lipgloss.NewStyle().
-	BorderStyle(lipgloss.RoundedBorder()).
+var contentBoxTitleStyle = lipgloss.NewStyle().
+	Border(viewportTitleBorder).
 	BorderForeground(inactiveBorderColor).
-	PaddingRight(1).
-	MarginBottom(1)
+	Padding(0, 2)
 
-var contentBoxActiveStyle = contentBoxStyle.Copy().
-	BorderStyle(lipgloss.RoundedBorder()).
-	BorderForeground(activeBorderColor)
+var contentBoxNoteStyle = lipgloss.NewStyle().
+	Border(viewportNoteBorder, true, true, true, false).
+	BorderForeground(inactiveBorderColor).
+	Padding(0, 2)
+
+var contentBoxStyle = lipgloss.NewStyle().
+	BorderStyle(viewportBodyBorder).
+	BorderForeground(inactiveBorderColor).
+	PaddingRight(1)
 
 var menuItemStyle = lipgloss.NewStyle().
 	Foreground(lipgloss.Color("252")).
@@ -49,7 +87,8 @@ var selectedMenuItemStyle = lipgloss.NewStyle().
 	Foreground(lipgloss.Color("207")).
 	PaddingLeft(1)
 
-var footerStyle = lipgloss.NewStyle()
+var footerStyle = lipgloss.NewStyle().
+	MarginTop(1)
 
 var helpKeyStyle = lipgloss.NewStyle().
 	Foreground(lipgloss.Color("241"))