Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

List Width not respected #744

Open
FFX01 opened this issue Feb 26, 2025 · 0 comments
Open

List Width not respected #744

FFX01 opened this issue Feb 26, 2025 · 0 comments

Comments

@FFX01
Copy link

FFX01 commented Feb 26, 2025

Describe the bug
When creating a new list, width is a required argument. This value does absolutely nothing unless it is set to a value smaller than the width of the widest list item. Looking through the code that implements list, I could not find anywhere in which the width member of the list.Model struct is used to force the rendering to the specified width. It does appear to be used in some capacity when rendering the filter input and the help section, but that's it. Even then, it does not appear to have an effect from my testing.

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

  • OS: KDE Neon
  • Shell: zsh
  • Terminal Emulator: Kitty
  • Terminal Multiplexer: N/A
  • Locale: US/UTF-8

To Reproduce
Steps to reproduce the behavior:

  1. Use list.New to create a new list. Set the width to a value larger than the width of your widest list item.
  2. render the list in your view function.
  3. Observe that list does not respect tha value of the width argument.

Source Code
This is the source code from following the tutorial in this video:

package main

import (
	"log"

	"github.com/charmbracelet/bubbles/list"
	tea "github.com/charmbracelet/bubbletea"
	"github.com/charmbracelet/lipgloss"
)

type status int

const layoutDivisor int = 4

const (
	todo status = iota
	inProgress
	done
)

/* Styling */
var (
	columnStyle = lipgloss.NewStyle().
			Padding(2, 1).
			Border(lipgloss.HiddenBorder())
	focusedStyle = lipgloss.NewStyle().
			Padding(2, 1).
			Border(lipgloss.RoundedBorder()).
			BorderForeground(lipgloss.Color("62"))
	helpStyle = lipgloss.NewStyle().
			Foreground(lipgloss.Color("41"))
)

/* Task List Item */

type Task struct {
	title       string
	description string
	status      status
}

func (t *Task) Title() string       { return t.title }
func (t *Task) Description() string { return t.description }
func (t *Task) FilterValue() string { return t.title }

/* Main Model */
type Model struct {
	focused status
	lists   []list.Model
	err     error
	loaded  bool
}

func NewModel() *Model {
	m := new(Model)
	return m
}

func (m *Model) onNextList() {
	if m.focused == done {
		m.focused = todo
	} else {
		m.focused++
	}
}

func (m *Model) onPrevList() {
	if m.focused == todo {
		m.focused = done
	} else {
		m.focused--
	}
}

func (m *Model) initLists(width, height int) {
	_, heightOffset := columnStyle.GetFrameSize()
    // listWidth := (width - (widthOffset * 3)) / 3
    listHeight := height - heightOffset
	defaultList := list.New([]list.Item{}, list.NewDefaultDelegate(), 10, listHeight)
	defaultList.SetShowHelp(false)

	m.lists = []list.Model{defaultList, defaultList, defaultList}

	m.lists[todo].Title = "Todo"
	m.lists[todo].SetItems([]list.Item{
		&Task{status: todo, title: "Buy Milk", description: "Strawberry Milk"},
		&Task{status: todo, title: "Eat Sushi", description: "California Roll"},
		&Task{status: todo, title: "Do Laundry", description: "Or have wrinkles"},
	})

	m.lists[inProgress].Title = "In Progress"
	m.lists[inProgress].SetItems([]list.Item{
		&Task{status: todo, title: "Be Cool", description: "You know it baby!"},
	})

	m.lists[done].Title = "Done"
	m.lists[done].SetItems([]list.Item{
		&Task{status: todo, title: "VetRec Interview 2", description: "Went well"},
		&Task{status: todo, title: "Learn Go", description: "Language Learned"},
	})

	m.loaded = true
}

func (m Model) Init() tea.Cmd {
	return nil
}

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

	switch msg := msg.(type) {
	case tea.WindowSizeMsg:
		m.initLists(msg.Width, msg.Height)
	case tea.KeyMsg:
		switch msg.String() {
		case "ctrl+c":
			return m, tea.Quit
		case "left":
			m.onPrevList()
		case "right":
			m.onNextList()
		case "tab":
			m.onNextList()
		}
	}

	m.lists[m.focused], cmd = m.lists[m.focused].Update(msg)
	return m, cmd
}

func (m Model) View() string {
	if !m.loaded {
		return "Loading..."
	}

	todoList := m.lists[todo].View()
	inProgressList := m.lists[inProgress].View()
	doneList := m.lists[done].View()

	switch m.focused {
	case todo:
		todoList = focusedStyle.Render(todoList)
		inProgressList = columnStyle.Render(inProgressList)
		doneList = columnStyle.Render(doneList)
	case inProgress:
		todoList = columnStyle.Render(todoList)
		inProgressList = focusedStyle.Render(inProgressList)
		doneList = columnStyle.Render(doneList)
	case done:
		todoList = columnStyle.Render(todoList)
		inProgressList = columnStyle.Render(inProgressList)
		doneList = focusedStyle.Render(doneList)
	}

	return lipgloss.JoinHorizontal(
		lipgloss.Center,
		todoList,
		inProgressList,
		doneList,
	)
}

func main() {
	model := NewModel()
	p := tea.NewProgram(model, tea.WithAltScreen())

	_, err := p.Run()
	if err != nil {
		log.Fatal(err)
	}
}

Expected behavior
The value passed to width when creating a new list via list.New should set the width of the rendered list component.

Screenshots

Screencast_20250226_141745.webm

Additional context
Add any other context about the problem here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant