charmbracelet / bubbles

TUI components for Bubble Tea 🫧
MIT License
5.24k stars 247 forks source link

fix(help): Fix help bubble not centering correctly #516

Closed gabe565 closed 2 months ago

gabe565 commented 3 months ago

The help bubble appends the separator after the final column, which results in it being shifted 4 cols to the left when centered. This PR removes the final separator column.

I don't know the reasoning for this decision, so feel free to close this if the final separator column is intended! If it is, maybe a bool should be added to toggle the behavior?

Fixes #415

Thank you!

Examples

ascii-movie I built [ascii-movie](https://github.com/gabe565/ascii-movie), and have seen this behavior. Here's a screenshot before and after the fix: **Before:** image **After:** image
simple repro **Before/After:** image **Code:** ```go package main import ( "fmt" "os" "github.com/charmbracelet/bubbles/help" "github.com/charmbracelet/bubbles/key" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" ) type keyMap struct { Up key.Binding Down key.Binding Left key.Binding Right key.Binding Help key.Binding Quit key.Binding } func (k keyMap) ShortHelp() []key.Binding { return []key.Binding{k.Help, k.Quit} } func (k keyMap) FullHelp() [][]key.Binding { return [][]key.Binding{ {k.Up, k.Down, k.Left, k.Right}, {k.Help, k.Quit}, } } var keys = keyMap{ Up: key.NewBinding( key.WithKeys("up", "k"), key.WithHelp("↑/k", "move up"), ), Down: key.NewBinding( key.WithKeys("down", "j"), key.WithHelp("↓/j", "move down"), ), Left: key.NewBinding( key.WithKeys("left", "h"), key.WithHelp("←/h", "move left"), ), Right: key.NewBinding( key.WithKeys("right", "l"), key.WithHelp("→/l", "move right"), ), Help: key.NewBinding( key.WithKeys("?"), key.WithHelp("?", "toggle help"), ), Quit: key.NewBinding( key.WithKeys("q", "esc", "ctrl+c"), key.WithHelp("q", "quit"), ), } type model struct { keys keyMap help help.Model style lipgloss.Style width, height int } func newModel() model { h := help.New() h.ShowAll = true return model{ keys: keys, help: h, style: lipgloss.NewStyle().Margin(2), } } 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, m.height = msg.Width, msg.Height case tea.KeyMsg: switch { case key.Matches(msg, m.keys.Help): m.help.ShowAll = !m.help.ShowAll case key.Matches(msg, m.keys.Quit): return m, tea.Quit } } return m, nil } func (m model) View() string { text := "Example text to test alignment\n" helpView := m.help.View(m.keys) content := lipgloss.JoinVertical(lipgloss.Center, text, helpView) return m.style.Render(content) } func main() { if _, err := tea.NewProgram(newModel()).Run(); err != nil { fmt.Printf("Could not start program :(\n%v\n", err) os.Exit(1) } } ```
meowgorithm commented 2 months ago

Thank you for the extremely thorough PR (ascii-movie looks awesome, btw)!