charmbracelet/lipgloss

`Style.Width()` and `Style.GetHorizontalFrameSize()` both include padding

qualidafial opened this issue · 0 comments

I am attempting to render a block of content to some size (e.g. to fill up the full width of the terminal). Based on the API docs, I intuitively expected to be able to do so using code like this:

style := lipgloss.NewStyle().Padding(0, 2).Border(lipgloss.NormalBorder(), true)
contentWidth := m.Width - style.GetHorizontalFrameSize()
rendered := style.Width(contentWidth).Render(content)

However when you dig down into the code, Style.Width sets the width including padding, and GetHorizontalFrameSize() also includes the padding width. So in the above case, contentWidth ends up being 4 spaces narrower than wanted.

Part of this stems from the current Style.Width(int) docs, which aren't very specific about what's happening:

Width sets the width of the block before applying margins. The width, if set, also determines where text will wrap.

Margins are mentioned, but padding and borders are not. It would be helpful if the documentation was more explicit about how each property will be used and which frame elements are and are not included in the width.

I attempted to use Style.MaxWidth(int) instead, but this causes the content to be truncated rather than word wrapped like what happens with Style.Width(int).

We could really use APIs that make it easier and more intuitive to set style sizes in order to achieve the layouts we want.

One option would be the ability to set the content size, where content is mutually exclusive from the frame sizes:

style := lipgloss.NewStyle().Padding(0, 2).Border(lipgloss.NormalBorder(), true)
contentWidth := m.Width - style.GetHorizontalFrameSize()
rendered := style.ContentWidth(contentWidth).Render(content)

However I think the most useful option would be to add methods that set the overall size of the content and frame together:

style := lipgloss.NewStyle().Padding(0, 2).Border(lipgloss.NormalBorder(), true)
rendered := style.OverallWidth(m.Width).Render(content)

With the expectation that the content would be word wrapped / truncated to overallWidth - horizontalFrameWidth.