Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: New Border Title API #97

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
31 changes: 31 additions & 0 deletions README.md
Expand Up @@ -203,6 +203,37 @@ lipgloss.NewStyle().
lipgloss.NewStyle().
Border(lipgloss.DoubleBorder(), true, false, false, true)
```
It is also possible to set and style a border title
```go

// create bold italic title horizontally aligned
// to center of the border
titleStyle := lipgloss.NewStyle().
Background(lipgloss.Color("#6124DF")).
Align(lipgloss.Center).
Bold(true).
Italic(true)

// dialog box style with its title styled
dialogBoxStyle := lipgloss.NewStyle().
Border(lipgloss.RoundedBorder()).
BorderForeground(lipgloss.Color("#874BFD")).
BorderTitleStyle(titleStyle).
Padding(1, 0).
BorderTop(true).
BorderLeft(true).
BorderRight(true).
BorderBottom(true)


// Use the title with the dialog box style
dialog := lipgloss.Place(width, 9,
lipgloss.Center, lipgloss.Center,
dialogBoxStyle.Copy().BorderTitle(" Question ").Render(ui),
lipgloss.WithWhitespaceChars("猫咪"),
lipgloss.WithWhitespaceForeground(subtle),
)
```

For more on borders see [the docs][docs].

Expand Down
39 changes: 37 additions & 2 deletions borders.go
Expand Up @@ -294,11 +294,45 @@ func (s Style) applyBorder(str string) string {
border.BottomLeft = getFirstRuneAsString(border.BottomLeft)

var out strings.Builder
const sideCount = 2

// Render top
if hasTop {
top := renderHorizontalEdge(border.TopLeft, border.Top, border.TopRight, width)
top = styleBorder(top, topFG, topBG)
top := ""

// sanitize title style
titleStyle := s.GetBorderTitleStyle().Copy().MaxWidth(width)

// set default padding if one is not set
if titleStyle.GetHorizontalPadding() == 0 {
titleStyle = titleStyle.Padding(0, 1)
}

title := s.GetBorderTitle()

if len(strings.TrimSpace(title)) > 0 {
titleLen := titleStyle.GetHorizontalFrameSize() + len(title)
topBeforeTitle := border.TopLeft
topAfterTitle := border.TopRight
switch titleStyle.GetAlignHorizontal() {
case Right:
topBeforeTitle = border.TopLeft + strings.Repeat(border.Top, max(0, width-1-titleLen))
case Center:
noTitleLen := width - 1 - titleLen
noTitleLen2 := noTitleLen / sideCount
topBeforeTitle = border.TopLeft + strings.Repeat(border.Top, max(0, noTitleLen2))
topAfterTitle = strings.Repeat(border.Top, max(0, noTitleLen-noTitleLen2)) + border.TopRight
case Left:
topAfterTitle = strings.Repeat(border.Top, max(0, width-1-titleLen)) + border.TopRight
}

top = styleBorder(topBeforeTitle, topFG, topBG) +
titleStyle.Render(title) +
styleBorder(topAfterTitle, topFG, topBG)
} else {
top = renderHorizontalEdge(border.TopLeft, border.Top, border.TopRight, width)
top = styleBorder(top, topFG, topBG)
}
out.WriteString(top)
out.WriteRune('\n')
}
Expand Down Expand Up @@ -362,6 +396,7 @@ func renderHorizontalEdge(left, middle, right string, width int) string {

out := strings.Builder{}
out.WriteString(left)

for i := leftWidth + rightWidth; i < width+rightWidth; {
out.WriteRune(runes[j])
j++
Expand Down
10 changes: 9 additions & 1 deletion example/main.go
Expand Up @@ -92,9 +92,17 @@ var (

// Dialog.

dialogTitleStyle = lipgloss.NewStyle().
Background(lipgloss.Color("#6124DF")).
Align(lipgloss.Center).
Bold(true).
Italic(true).
Padding(0, 5)

dialogBoxStyle = lipgloss.NewStyle().
Border(lipgloss.RoundedBorder()).
BorderForeground(lipgloss.Color("#874BFD")).
BorderTitleStyle(dialogTitleStyle).
Padding(1, 0).
BorderTop(true).
BorderLeft(true).
Expand Down Expand Up @@ -239,7 +247,7 @@ func main() {

dialog := lipgloss.Place(width, 9,
lipgloss.Center, lipgloss.Center,
dialogBoxStyle.Render(ui),
dialogBoxStyle.Copy().BorderTitle("Question").Render(ui),
lipgloss.WithWhitespaceChars("猫咪"),
lipgloss.WithWhitespaceForeground(subtle),
)
Expand Down
32 changes: 31 additions & 1 deletion get.go
Expand Up @@ -434,6 +434,24 @@ func (s Style) getAsInt(k propKey) int {
return 0
}

func (s Style) getAsString(k propKey) string {
if v, ok := s.rules[k]; ok {
if s, ok := v.(string); ok {
return s
}
}
return ""
}

func (s Style) getAsStyle(k propKey) Style {
if v, ok := s.rules[k]; ok {
if s, ok := v.(Style); ok {
return s
}
}
return NewStyle()
}

func (s Style) getAsPosition(k propKey) Position {
v, ok := s.rules[k]
if !ok {
Expand All @@ -456,7 +474,19 @@ func (s Style) getBorderStyle() Border {
return noBorder
}

// Split a string into lines, additionally returning the size of the widest
// GetBorderTitleStyle returns border title style if set,
// otherwise returns empty style.
func (s Style) GetBorderTitleStyle() Style {
return s.getAsStyle(borderTitleStyleKey)
}

// GetBorderTitle returns border title if set,
// otherwise returns empty string.
func (s Style) GetBorderTitle() string {
return s.getAsString(borderTitleKey)
}

// Split a string into lines, additionally returning the size of the widest.
// line.
func getLines(s string) (lines []string, widest int) {
lines = strings.Split(s, "\n")
Expand Down
12 changes: 12 additions & 0 deletions set.go
Expand Up @@ -455,6 +455,18 @@ func (s Style) BorderLeftBackground(c TerminalColor) Style {
return s
}

// BorderTitleStyle set border title style
func (s Style) BorderTitleStyle(style Style) Style {
s.set(borderTitleStyleKey, style)
return s
}

// BorderTitle set border title
func (s Style) BorderTitle(title string) Style {
s.set(borderTitleKey, title)
return s
}

// Inline makes rendering output one line and disables the rendering of
// margins, padding and borders. This is useful when you need a style to apply
// only to font rendering and don't want it to change any physical dimensions.
Expand Down
4 changes: 4 additions & 0 deletions style.go
Expand Up @@ -65,6 +65,10 @@ const (
borderBottomBackgroundKey
borderLeftBackgroundKey

// Border title.
borderTitleStyleKey
borderTitleKey

inlineKey
maxWidthKey
maxHeightKey
Expand Down