Skip to content

Instantly share code, notes, and snippets.

@meowgorithm
Last active February 15, 2024 19:55
Show Gist options
  • Save meowgorithm/1777377a43373f563476a2bcb7d89306 to your computer and use it in GitHub Desktop.
Save meowgorithm/1777377a43373f563476a2bcb7d89306 to your computer and use it in GitHub Desktop.
Lip Gloss Box with Label
package main
import (
"fmt"
"strings"
"github.com/charmbracelet/lipgloss"
)
type BoxWithLabel struct {
BoxStyle lipgloss.Style
LabelStyle lipgloss.Style
}
func NewDefaultBoxWithLabel() BoxWithLabel {
return BoxWithLabel{
BoxStyle: lipgloss.NewStyle().
Border(lipgloss.RoundedBorder()).
BorderForeground(lipgloss.Color("63")).
Padding(1),
// You could, of course, also set background and foreground colors here
// as well.
LabelStyle: lipgloss.NewStyle().
PaddingTop(0).
PaddingBottom(0).
PaddingLeft(1).
PaddingRight(1),
}
}
func (b BoxWithLabel) Render(label, content string, width int) string {
var (
// Query the box style for some of its border properties so we can
// essentially take the top border apart and put it around the label.
border lipgloss.Border = b.BoxStyle.GetBorderStyle()
topBorderStyler func(string) string = lipgloss.NewStyle().Foreground(b.BoxStyle.GetBorderTopForeground()).Render
topLeft string = topBorderStyler(border.TopLeft)
topRight string = topBorderStyler(border.TopRight)
renderedLabel string = b.LabelStyle.Render(label)
)
// Render top row with the label
borderWidth := b.BoxStyle.GetHorizontalBorderSize()
cellsShort := max(0, width+borderWidth-lipgloss.Width(topLeft+topRight+renderedLabel))
gap := strings.Repeat(border.Top, cellsShort)
top := topLeft + renderedLabel + topBorderStyler(gap) + topRight
// Render the rest of the box
bottom := b.BoxStyle.Copy().
BorderTop(false).
Width(width).
Render(content)
// Stack the pieces
return top + "\n" + bottom
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
func main() {
const body = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam imperdiet ultrices felis, et condimentum odio fringilla et. Etiam porttitor volutpat diam non gravida. Donec et condimentum nulla. Sed consectetur viverra fermentum. Pellentesque eget metus ut felis faucibus consectetur nec ac mi."
b := NewDefaultBoxWithLabel()
fmt.Println(b.Render("Title", body, 40))
}
@meowgorithm
Copy link
Author

Output:

Example

@jzandbergen
Copy link

Thank you very much for this. One small update; I had to use topBorderStyler func(...string) instead of topBorderStyler func(string). I think it changed in lipgloss here

@eugener
Copy link

eugener commented Feb 15, 2024

Another change is to preserve box style background within the Render method.

topBorderStyler = lipgloss.NewStyle().
				Foreground(b.BoxStyle.GetBorderTopForeground()).
				Background(b.BoxStyle.GetBorderTopBackground()).
				Render

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment