Viewport's maxYOffset() should consider top / bottom borders
Zebbeni opened this issue · comments
Andrew Albers commented
When a border style is applied to a viewport, the last line (or two lines) of the viewport's rendered content will be hidden when scrolling or calling SetYOffset()
. This is because setting YOffset is clamped to maxYOffset()
, which doesn't account for the fact that a border subtracts from its content-renderable height.
Ex. Identical content rendered in un-bordered & bordered viewports after scrolling all the way down
(note that line 9 and line 10 cannot be reached):
Example code
package main
import (
"fmt"
"os"
"github.com/charmbracelet/bubbles/viewport"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
)
const (
viewH = 5
viewW = 10
content = "line 1\nline 2\nline 3\nline 4\nline 5\nline 6\nline 7\nline 8\nline 9\nline 10"
)
var (
borderStyle = lipgloss.NewStyle().Border(lipgloss.RoundedBorder())
noBorderStyle = lipgloss.NewStyle()
)
type model struct {
view1 viewport.Model
view2 viewport.Model
}
func (m *model) Init() tea.Cmd {
return nil
}
func (m *model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.view1, _ = m.view1.Update(msg)
m.view2, _ = m.view2.Update(msg)
return m, nil
}
func (m *model) View() string {
view1Content := m.view1.View()
view2Content := m.view2.View()
combined := lipgloss.JoinHorizontal(lipgloss.Left, view1Content, view2Content)
return combined
}
func main() {
view1 := viewport.New(viewW, viewH)
view1.Style = noBorderStyle
view1.SetContent(content)
view2 := viewport.New(viewW, viewH)
view2.Style = borderStyle
view2.SetContent(content)
m := &model{
view1: view1,
view2: view2,
}
p := tea.NewProgram(m)
if _, err := p.Run(); err != nil {
fmt.Println("Run error:", err)
os.Exit(1)
}
}
Andrew Albers commented
Created a PR with my suggested fix: #337