charmbracelet / bubbletea

A powerful little TUI framework 🏗
MIT License
26.76k stars 771 forks source link

Setting a border around a list results in "breaks" when scrolling the list #239

Closed er4hn closed 2 years ago

er4hn commented 2 years ago

Hello,

First off, the whole charmbracelet thing is awesome. Really enjoying what a modern TUI is capable of.

I'm trying to make a list with a border. The idea is I would have a couple different lists, aligned horizontally, kind of like what is done with soft-serve. I'm having an issue however where scrolling through a toy list results in "breaks" in the list border.

You can recreate this issue by changing https://github.com/charmbracelet/bubbletea/blob/62259b72e5533f1411327444d1baf68355327bdf/examples/list-default/main.go#L12 to be:

var docStyle = lipgloss.NewStyle().Margin(1, 2).BorderStyle(lipgloss.NormalBorder()).BorderForeground(lipgloss.Color("63"))

and then scrolling up and down. I've included a picture as well to show what I'm talking about. The picture is from the tmux terminal.

I'm able to have this occur in a Pop_OS (Ubuntu) terminal running tmux, a terminal not running tmux, as well as a VS Code terminal ssh'ed to the Pop_OS instance.

image

meowgorithm commented 2 years ago

Hi! This is because the style you're applying is causing the list to run higher than the vertical height of the terminal. To fix it we need to change the code that measures the margins to instead measure all the vertical space that's being taken up by the margins, borders and padding. There's a Lip Gloss style method for this called GetFrameSize.

So just change lines 38 and 39 to:

v, h := docStyle.GetFrameSize()
m.list.SetSize(msg.Width-h, msg.Height-v)

Here's a patch:

diff --git a/examples/list-default/main.go b/examples/list-default/main.go
index e7b1d6b..73c84a4 100644
--- a/examples/list-default/main.go
+++ b/examples/list-default/main.go
@@ -9,7 +9,7 @@ import (
    "github.com/charmbracelet/lipgloss"
 )

-var docStyle = lipgloss.NewStyle().Margin(1, 2)
+var docStyle = lipgloss.NewStyle().Margin(1, 2).BorderStyle(lipgloss.NormalBorder()).BorderForeground(lipgloss.Color("63"))

 type item struct {
    title, desc string
@@ -34,8 +34,8 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
            return m, tea.Quit
        }
    case tea.WindowSizeMsg:
-       top, right, bottom, left := docStyle.GetMargin()
-       m.list.SetSize(msg.Width-left-right, msg.Height-top-bottom)
+       v, h := docStyle.GetFrameSize()
+       m.list.SetSize(msg.Width-h, msg.Height-v)
    }

    var cmd tea.Cmd

And here's some sample output:

Screen Shot 2022-02-21 at 8 45 11 PM

And let us know if you have any more questions!

er4hn commented 2 years ago

Thanks for the explanation! This works... dare I say it... like a charm 😄