bubbles icon indicating copy to clipboard operation
bubbles copied to clipboard

v2: textinput overflows set width

Open lrstanley opened this issue 5 months ago • 0 comments

Describe the bug When setting the width on the textinput component, it will overflow the provided width. Additionally, the width is also variable depending on suggestions provided to the input (it will increase in width even further beyond the limit when a suggestion is showing).

Setup

  • OS: Ubuntu (WSL2)
  • Shell: Bash
  • Terminal Emulator: Windows Terminal
  • Terminal Multiplexer: n/a
  • Locale: en_US.UTF-8

To Reproduce Run the below example using bubbles/bubbletea/lipgloss v2, and it should panic anytime the width of the textinput does not obey what was provided with <input>.SetWidth(int)

Source Code

package main

import (
	"fmt"
	"log"

	"github.com/charmbracelet/bubbles/v2/textinput"
	tea "github.com/charmbracelet/bubbletea/v2"
	"github.com/charmbracelet/lipgloss/v2"
)

const InputWidth = 20

func main() {
	p := tea.NewProgram(initialModel(), tea.WithAltScreen())
	if _, err := p.Run(); err != nil {
		log.Fatal(err)
	}
}

type model struct {
	input textinput.Model
}

func initialModel() model {
	ti := textinput.New()
	ti.Placeholder = "Pikachu"
	ti.Focus()
	ti.VirtualCursor = true
	ti.SetWidth(InputWidth)

	return model{input: ti}
}

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

func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
	var cmd tea.Cmd

	switch msg := msg.(type) {
	case tea.KeyPressMsg:
		switch msg.String() {
		case "enter", "ctrl+c", "esc":
			return m, tea.Quit
		}
	}

	m.input, cmd = m.input.Update(msg)
	return m, cmd
}

func (m model) View() string {
	input := m.input.View()

	if lipgloss.Width(input) > InputWidth {
		panic(fmt.Sprintf("input width is %d", lipgloss.Width(input)))
	}

	return lipgloss.JoinVertical(
		lipgloss.Top,
		m.headerView(),
		input,
		m.footerView(),
	)
}

func (m model) headerView() string { return "What's your favorite Pokémon?\n" }
func (m model) footerView() string { return "\n(esc to quit)" }

Expected behavior I would expect that it should obey the provided width and handle any form of truncating internally.

Screenshots n/a

Additional context A user could obviously wrap the input and force cut off the width, but this should not be required.

lrstanley avatar Jul 14 '25 05:07 lrstanley