charmbracelet / charmbracelet/bubbles
List: Unnecessary/Undesirable ellipsis on full width title
- Dominant language
- Go
- Stars
- 8.9k
- Forks
- 457
- Avg merge
- 1d 18h
- Merged PRs (30d)
- 5
Description
**Describe the bug**
When the list title occupies the full width of the item, unnecessary ellipsis is appended. The logic which appends the status message appends two spaces regardless of whether a status message is set.
**Setup**
Please complete the following information along with version numbers, if applicable.
- OS agnostic
- Shell agnostic
- Terminal Emulator: n/a
- Terminal Multiplexer: n/a
- Locale en_US.UTF-8
**To Reproduce**
Steps to reproduce the behavior:
1. Create a list with a title set to the maximum width (but no wider)
``` dl := list.New(listItems, itemDelegate, 0, 10)
dl.SetShowHelp(false)
dl.Title = "List Title ABCDEFG"
dl.Styles.Title = list.DefaultStyles().Title.Padding(0)
```
2. Set the list width to title width + 2 (in the example above 18 + 2 = 20)
3. Render the list
**Source Code**
```package main
import (
"fmt"
"github.com/charmbracelet/bubbles/list"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
)
type someListModel struct {
demoList list.Model
}
type someListItem struct {
text string
}
func (s someListItem) FilterValue() string {
return s.text
}
func (s someListItem) Description() string {
return ""
}
var listItemStyle = lipgloss.NewStyle().Width(18).Background(lipgloss.Color("17")).Foreground(lipgloss.Color("15")).Align(lipgloss.Left)
func (s someListItem) Title() string {
return listItemStyle.Render(s.text)
}
func NewList(items []string) *someListModel {
listItems := make([]list.Item, len(items))
for i, item := range items {
listItems[i] = someListItem{text: item}
}
itemDelegate := list.NewDefaultDelegate()
itemDelegate.SetHeight(1)
itemDelegate.SetSpacing(0)
itemDelegate.ShowDescription = false
dl := list.New(listItems, itemDelegate, 0, 10)
dl.SetShowHelp(false)
dl.Title = "List Title ABCDEFG"
dl.Styles.Title = list.DefaultStyles().Title.Padding(0)
return &someListModel{demoList: dl}
}
func (s *someListModel) Init() tea.Cmd {
return nil
}
func (s *someListModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.WindowSizeMsg:
s.demoList.SetWidth(min(20, msg.Width-2))
case tea.KeyMsg:
if s.demoList.FilteringEnabled() {
break
}
if msg.String() == "q" {
return s, tea.Quit
}
}
var cmd tea.Cmd
s.demoList, cmd = s.demoList.Update(msg)
return s, cmd
}
func (s *someListModel) View() string {
return lipgloss.NewStyle().Border(lipgloss.NormalBorder()).Render(s.demoList.View())
}
func main() {
s := NewList([]string{"one", "two", "three"})
p := tea.NewProgram(s, tea.WithAltScreen())
if _, err := p.Run(); err != nil {
fmt.Printf("Error starting program: %v", err)
return
}
}
```
**Expected behavior**
Given the title itself doesn't overflow the width of the list, I would not expect an ellipsis to be appended to the title.
**Screenshots**

**Additional context**
The origin of the problem is the unconditional appending of two spaces to the title (assuming filtering is not active)
``` // Status message
if m.filterState != Filtering {
view += " " + m.statusMessage
view = ansi.Truncate(view, m.width-spinnerWidth, ellipsis)
}```
If the spaces were only appended for non-empty statusMessage, this would only result in the ellipsis in the valid situation where there is further content beyond the base title.
``` // Status message
if m.filterState != Filtering {
if m.statusMessage != "" {
view += " " + m.statusMessage
}
view = ansi.Truncate(view, m.width-spinnerWidth, ellipsis)
}
```
This yields the title without the ellipsis.

Contributor guide
Assessment
This issue has not been assessed yet.