Skip to content

bug: Double border when Base style has a border and textarea shows placeholder #1643

@Acksell

Description

@Acksell

Describe the bug

When setting a Border on the textarea's styles.Focused.Base (or Blurred.Base), the border is rendered twice while the placeholder is visible (empty textarea). Once the user types any text, the double border disappears and only a single border is shown.

The inner border appears shifted by the border + padding offset, producing a nested-box effect.

Image Image

Setup
Please complete the following information along with version numbers, if applicable.

  • OS: macOS
  • Shell: zsh
  • Terminal Emulator: Ghostty
  • Terminal Multiplexer: N/A

To Reproduce
Run the following code snippet below

Source Code

package main

import (
	"fmt"
	"os"

	"charm.land/bubbles/v2/textarea"
	tea "charm.land/bubbletea/v2"
	"charm.land/lipgloss/v2"
)

type model struct {
	ta textarea.Model
}

func initialModel() model {
	ta := textarea.New()
	ta.Placeholder = "Type something..."
	ta.ShowLineNumbers = false
	ta.Prompt = ""
	ta.SetHeight(5)

	// Set a border on Base — this triggers the double-render bug.
	styles := ta.Styles()
	styles.Focused.Base = lipgloss.NewStyle().
		Border(lipgloss.RoundedBorder()).
		BorderForeground(lipgloss.Color("63")).
		Padding(0, 1)
	styles.Blurred.Base = styles.Focused.Base
	styles.Focused.CursorLine = lipgloss.NewStyle()
	ta.SetStyles(styles)

	ta.Focus()
	return model{ta: ta}
}

func (m model) Init() tea.Cmd {
	return m.ta.Focus()
}

func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
	switch msg := msg.(type) {
	case tea.KeyPressMsg:
		if msg.String() == "ctrl+c" {
			return m, tea.Quit
		}
	case tea.WindowSizeMsg:
		m.ta.SetWidth(msg.Width)
	}
	var cmd tea.Cmd
	m.ta, cmd = m.ta.Update(msg)
	return m, cmd
}

func (m model) View() tea.View {
	return tea.NewView(fmt.Sprintf("\n%s\n\nctrl+c to quit\n", m.ta.View()))
}

func main() {
	p := tea.NewProgram(initialModel())
	if _, err := p.Run(); err != nil {
		fmt.Fprintf(os.Stderr, "error: %v\n", err)
		os.Exit(1)
	}
}

Expected behavior
No inner or double border, just a single border in the textarea, regardless of if text is in the box or not.

Screenshots
See above

Additional context
This report is largely AI generated.

go mod:

module test

go 1.26.0

require (
	charm.land/bubbles/v2 v2.0.0
	charm.land/bubbletea/v2 v2.0.2
	charm.land/lipgloss/v2 v2.0.2
)

require (
	github.com/atotto/clipboard v0.1.4 // indirect
	github.com/charmbracelet/colorprofile v0.4.2 // indirect
	github.com/charmbracelet/ultraviolet v0.0.0-20260205113103-524a6607adb8 // indirect
	github.com/charmbracelet/x/ansi v0.11.6 // indirect
	github.com/charmbracelet/x/term v0.2.2 // indirect
	github.com/charmbracelet/x/termios v0.1.1 // indirect
	github.com/charmbracelet/x/windows v0.2.2 // indirect
	github.com/clipperhouse/displaywidth v0.11.0 // indirect
	github.com/clipperhouse/uax29/v2 v2.7.0 // indirect
	github.com/lucasb-eyer/go-colorful v1.3.0 // indirect
	github.com/mattn/go-runewidth v0.0.20 // indirect
	github.com/muesli/cancelreader v0.2.2 // indirect
	github.com/rivo/uniseg v0.4.7 // indirect
	github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
	golang.org/x/sync v0.19.0 // indirect
	golang.org/x/sys v0.42.0 // indirect
)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions