lipgloss icon indicating copy to clipboard operation
lipgloss copied to clipboard

Add innerBorder style

Open AlyxPractice opened this issue 3 years ago • 2 comments

By having the same color for the border and the background of the element, it gives some cool results: image

For context, in a game where you can buy upgrades, you can show the user the ones that have been already bought, the ones they can buy, and the ones still locked:

image

I think it could be a useful addition, for example when you want to highlight something as if it was a button.


Quick testing:

package main

import (
	"fmt"

	"github.com/charmbracelet/lipgloss"
)

var (
	innerBorder = lipgloss.Border{
		Top:         "▄",
		Bottom:      "▀",
		Left:        "▐",
		Right:       "▌",
		TopLeft:     "▗",
		TopRight:    "▖",
		BottomLeft:  "▝",
		BottomRight: "▘",
	}
)

func main() {
	fmt.Println()
	color := lipgloss.Color("#00f5d4)")
	testBorders := lipgloss.NewStyle().Foreground(lipgloss.Color("#333")).Background(color).BorderForeground(color)
	fmt.Println(testBorders.Copy().Border(lipgloss.NormalBorder()).Render("NormalBorder"))
	fmt.Println(testBorders.Copy().Border(lipgloss.RoundedBorder()).Render("RoundedBorder"))
	fmt.Println(testBorders.Copy().Border(innerBorder).Render("InnerBorder"))
	fmt.Println(testBorders.Copy().Border(lipgloss.ThickBorder()).Render("ThickBorder"))
	fmt.Println(testBorders.Copy().Border(lipgloss.DoubleBorder()).Render("DoubleBorder"))
	fmt.Println(testBorders.Copy().Border(lipgloss.HiddenBorder()).Render("HiddenBorder"))
}

AlyxPractice avatar Sep 04 '22 13:09 AlyxPractice

This is great; thanks for the PR. My only thought here is the name, since the effect you're going for in your example could also be done with inner padding. I wonder if there's anything else that's perhaps more clear. Maybe BlockBorder?

meowgorithm avatar Sep 05 '22 02:09 meowgorithm

since the effect you're going for in your example could also be done with inner padding

If I'm not mistaken, inner padding + background would create a larger border effect (notice the size of the top/bottom border): image

Maybe BlockBorder?

My reasoning behind the name was that by organizing the characters differently and changing corners blocks, you would get some kind of outer border, and by using a full-width block character, you would get another effect too (fullBorder), same as for Padding(1) with a width difference, as the border would be added to Width() where Padding() is part of the Width set (IIRC): image

I'm of course all open to renaming it to something else, but at least you have more context now 😊 Maybe something like HalfBlockBorder? InnerHalfBlockBorder?

The characters come from here, if needed: https://en.wikipedia.org/wiki/Box-drawing_character#Block_Elements And the Unicode standard for these characters, with their names in it: http://www.unicode.org/charts/PDF/U2580.pdf

Here's a new version of the demo, with a standardized width to easily compare them together:

image
package main

import (
	"fmt"

	"github.com/charmbracelet/lipgloss"
)

var (
	fullBorder = lipgloss.Border{
		Top:         "█",
		Bottom:      "█",
		Left:        "█",
		Right:       "█",
		TopLeft:     "█",
		TopRight:    "█",
		BottomLeft:  "█",
		BottomRight: "█",
	}
	outerBorder = lipgloss.Border{
		Top:         "▀",
		Bottom:      "▄",
		Left:        "▌",
		Right:       "▐",
		TopLeft:     "▛",
		TopRight:    "▜",
		BottomLeft:  "▙",
		BottomRight: "▟",
	}
	innerBorder = lipgloss.Border{
		Top:         "▄",
		Bottom:      "▀",
		Left:        "▐",
		Right:       "▌",
		TopLeft:     "▗",
		TopRight:    "▖",
		BottomLeft:  "▝",
		BottomRight: "▘",
	}
)

func main() {
	fmt.Println()
	color := lipgloss.Color("#00f5d4)")
	testBorders := lipgloss.NewStyle().Foreground(lipgloss.Color("#333")).Background(color).BorderForeground(color).Width(15)
	fmt.Println(testBorders.Copy().Border(lipgloss.NormalBorder()).Render("NormalBorder"))
	fmt.Println(testBorders.Copy().Border(lipgloss.RoundedBorder()).Render("RoundedBorder"))
	fmt.Println(testBorders.Copy().Border(fullBorder).Render("FullBorder"))
	fmt.Println(testBorders.Copy().Border(innerBorder).Render("InnerBorder"))
	fmt.Println(testBorders.Copy().Border(outerBorder).Render("OuterBorder"))
	fmt.Println(testBorders.Copy().Border(lipgloss.ThickBorder()).Render("ThickBorder"))
	fmt.Println(testBorders.Copy().Border(lipgloss.DoubleBorder()).Render("DoubleBorder"))
	fmt.Println(testBorders.Copy().Border(lipgloss.HiddenBorder()).Render("HiddenBorder"))
	fmt.Println(testBorders.Copy().Padding(1).Render("WithPadding1"))
}

AlyxPractice avatar Sep 05 '22 08:09 AlyxPractice

Not 100% sure on this but maybe this could be called OutlineBorder? Since it acts as an outline. If the full outline border is also introduced it could be OutlineBorder and ThickOutlineBorder? Or, perhaps InnerOutlineBorder / OuterOutlineBorder / FullOutlineBorder.

Thinking about this a bit more, I think BlockBorder and InnerHalfBlockBorder and OuterHalfBlockBorder also make a lot of sense.

maaslalani avatar Sep 20 '22 19:09 maaslalani

Love the names! I will edit my PR and add the new ones too.

AlyxPractice avatar Sep 21 '22 12:09 AlyxPractice

Hey, I took a while to get back on it, thanks for your patience 🙇

Here are the results with the new names and variations: image

What do you think? Anything else I can do? 😊

AlyxPractice avatar Oct 27 '22 17:10 AlyxPractice

Thanks so much @VictorBersy, this looks great!

maaslalani avatar Oct 27 '22 19:10 maaslalani