lipgloss icon indicating copy to clipboard operation
lipgloss copied to clipboard

fix: include borders in width calculation

Open samox73 opened this issue 4 months ago • 1 comments

Fix for https://github.com/charmbracelet/lipgloss/issues/298#issuecomment-2512430754

This PR ensures Style.Width() applies to the total rendered width, including borders and padding. This fixes cases where text with borders overflowed the set width.

  • Wrap width now subtracts both padding and border size.
  • Horizontal alignment uses the inner width (excluding borders).
  • Added tests to verify rendered output never exceeds the configured width.

demo

Example program to see the issue live:

package main

import (
	"fmt"

	"github.com/charmbracelet/bubbles/list"
	tea "github.com/charmbracelet/bubbletea"
	"github.com/charmbracelet/lipgloss"
)

type item struct {
	title string
	desc  string
}

func (i item) Title() string       { return i.title }
func (i item) Description() string { return i.desc }
func (i item) FilterValue() string { return i.title }

type model struct {
	list           list.Model
	width          int
	containerStyle lipgloss.Style
}

func newModel() model {
	items := make([]list.Item, 0, 10)
	for n := 1; n <= 10; n++ {
		items = append(items, item{
			title: fmt.Sprintf("Item %d", n),
			desc:  "Placeholder description",
		})
	}

	delegate := list.NewDefaultDelegate()
	l := list.New(items, delegate, 0, 0)
	l.Title = "Test"

	m := model{list: l}
	m.containerStyle = lipgloss.NewStyle().
		Border(lipgloss.RoundedBorder()).
		Padding(0, 1)
	return m
}

func (m model) Init() tea.Cmd { return nil }

func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
	switch msg := msg.(type) {
	case tea.WindowSizeMsg:
		m.width = msg.Width
		wFrame, hFrame := m.containerStyle.GetFrameSize()
		wList := msg.Width - wFrame
		hList := msg.Height - hFrame
		m.list.SetSize(wList, hList)
		return m, nil
	default:
		var cmd tea.Cmd
		m.list, cmd = m.list.Update(msg)
		return m, cmd
	}
}

func (m model) View() string {
	c := m.containerStyle
	s := c.Width(m.width)
	return s.Render(m.list.View())
}

func main() {
	p := tea.NewProgram(newModel(), tea.WithAltScreen())
	if _, err := p.Run(); err != nil {
		fmt.Println("Error:", err)
	}
}

samox73 avatar Sep 10 '25 10:09 samox73

Just a heads up that we haven't forgotten about this one, @samox73.

It might also be worth checking to see if this is still valid in the v2-exp branch as we're more or less approaching a v2-release and all our new efforts are going there.

meowgorithm avatar Oct 08 '25 17:10 meowgorithm