Dynamic table size #1316
Replies: 3 comments 2 replies
-
|
Would love to see an example of this as well. |
Beta Was this translation helpful? Give feedback.
-
|
Messed around with this a bit more and came up with the following example which will resize the column width based on the column contents or the table's parent container width. The parent container could be a lipgloss style (like in this example which fit my use case) or the current terminal width tracked by the model: package main
import (
"fmt"
"os"
"github.com/charmbracelet/bubbles/table"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
)
func initialModel() model {
columns := []table.Column{
{Title: "Rank"},
{Title: "City"},
{Title: "Country"},
{Title: "Population"},
}
rows := []table.Row{
{"1", "Tokyo", "Japan", "37,274,000"},
{"2", "Delhi", "India", "32,065,760"},
{"3", "Shanghai", "China", "28,516,904"},
{"4", "Dhaka", "Bangladesh", "22,478,116"},
{"5", "São Paulo", "Brazil", "22,429,800"},
{"6", "Mexico City", "Mexico", "22,085,140"},
{"7", "Cairo", "Egypt", "21,750,020"},
{"8", "Beijing", "China", "21,333,332"},
{"9", "Mumbai", "India", "20,961,472"},
{"10", "Osaka", "Japan", "19,059,856"},
{"11", "Chongqing", "China", "16,874,740"},
{"12", "Karachi", "Pakistan", "16,839,950"},
{"13", "Istanbul", "Turkey", "15,636,243"},
{"14", "Kinshasa", "DR Congo", "15,628,085"},
{"15", "Lagos", "Nigeria", "15,387,639"},
{"16", "Buenos Aires", "Argentina", "15,369,919"},
{"17", "Kolkata", "India", "15,133,888"},
{"18", "Manila", "Philippines", "14,406,059"},
{"19", "Tianjin", "China", "14,011,828"},
{"20", "Guangzhou", "China", "13,964,637"},
{"21", "Rio De Janeiro", "Brazil", "13,634,274"},
{"22", "Lahore", "Pakistan", "13,541,764"},
{"23", "Bangalore", "India", "13,193,035"},
{"24", "Shenzhen", "China", "12,831,330"},
{"25", "Moscow", "Russia", "12,640,818"},
{"26", "Chennai", "India", "11,503,293"},
{"27", "Bogota", "Colombia", "11,344,312"},
{"28", "Paris", "France", "11,142,303"},
{"29", "Jakarta", "Indonesia", "11,074,811"},
{"30", "Lima", "Peru", "11,044,607"},
{"31", "Bangkok", "Thailand", "10,899,698"},
{"32", "Hyderabad", "India", "10,534,418"},
{"33", "Seoul", "South Korea", "9,975,709"},
{"34", "Nagoya", "Japan", "9,571,596"},
{"35", "London", "United Kingdom", "9,540,576"},
{"36", "Chengdu", "China", "9,478,521"},
{"37", "Nanjing", "China", "9,429,381"},
{"38", "Tehran", "Iran", "9,381,546"},
{"39", "Ho Chi Minh City", "Vietnam", "9,077,158"},
{"40", "Luanda", "Angola", "8,952,496"},
{"41", "Wuhan", "China", "8,591,611"},
{"42", "Xi An Shaanxi", "China", "8,537,646"},
{"43", "Ahmedabad", "India", "8,450,228"},
{"44", "Kuala Lumpur", "Malaysia", "8,419,566"},
{"45", "New York City", "United States", "8,177,020"},
{"46", "Hangzhou", "China", "8,044,878"},
{"47", "Surat", "India", "7,784,276"},
{"48", "Suzhou", "China", "7,764,499"},
{"49", "Hong Kong", "Hong Kong", "7,643,256"},
{"50", "Riyadh", "Saudi Arabia", "7,538,200"},
{"51", "Shenyang", "China", "7,527,975"},
{"52", "Baghdad", "Iraq", "7,511,920"},
{"53", "Dongguan", "China", "7,511,851"},
{"54", "Foshan", "China", "7,497,263"},
{"55", "Dar Es Salaam", "Tanzania", "7,404,689"},
{"56", "Pune", "India", "6,987,077"},
{"57", "Santiago", "Chile", "6,856,939"},
{"58", "Madrid", "Spain", "6,713,557"},
{"59", "Haerbin", "China", "6,665,951"},
{"60", "Toronto", "Canada", "6,312,974"},
{"61", "Belo Horizonte", "Brazil", "6,194,292"},
{"62", "Khartoum", "Sudan", "6,160,327"},
{"63", "Johannesburg", "South Africa", "6,065,354"},
{"64", "Singapore", "Singapore", "6,039,577"},
{"65", "Dalian", "China", "5,930,140"},
{"66", "Qingdao", "China", "5,865,232"},
{"67", "Zhengzhou", "China", "5,690,312"},
{"68", "Ji Nan Shandong", "China", "5,663,015"},
{"69", "Barcelona", "Spain", "5,658,472"},
{"70", "Saint Petersburg", "Russia", "5,535,556"},
{"71", "Abidjan", "Ivory Coast", "5,515,790"},
{"72", "Yangon", "Myanmar", "5,514,454"},
{"73", "Fukuoka", "Japan", "5,502,591"},
{"74", "Alexandria", "Egypt", "5,483,605"},
{"75", "Guadalajara", "Mexico", "5,339,583"},
{"76", "Ankara", "Turkey", "5,309,690"},
{"77", "Chittagong", "Bangladesh", "5,252,842"},
{"78", "Addis Ababa", "Ethiopia", "5,227,794"},
{"79", "Melbourne", "Australia", "5,150,766"},
{"80", "Nairobi", "Kenya", "5,118,844"},
{"81", "Hanoi", "Vietnam", "5,067,352"},
{"82", "Sydney", "Australia", "5,056,571"},
{"83", "Monterrey", "Mexico", "5,036,535"},
{"84", "Changsha", "China", "4,809,887"},
{"85", "Brasilia", "Brazil", "4,803,877"},
{"86", "Cape Town", "South Africa", "4,800,954"},
{"87", "Jiddah", "Saudi Arabia", "4,780,740"},
{"88", "Urumqi", "China", "4,710,203"},
{"89", "Kunming", "China", "4,657,381"},
{"90", "Changchun", "China", "4,616,002"},
{"91", "Hefei", "China", "4,496,456"},
{"92", "Shantou", "China", "4,490,411"},
{"93", "Xinbei", "Taiwan", "4,470,672"},
{"94", "Kabul", "Afghanistan", "4,457,882"},
{"95", "Ningbo", "China", "4,405,292"},
{"96", "Tel Aviv", "Israel", "4,343,584"},
{"97", "Yaounde", "Cameroon", "4,336,670"},
{"98", "Rome", "Italy", "4,297,877"},
{"99", "Shijiazhuang", "China", "4,285,135"},
{"100", "Montreal", "Canada", "4,276,526"},
}
t := table.New(
table.WithColumns(columns),
table.WithRows(rows),
table.WithFocused(true),
)
return model{
table: t,
}
}
type model struct {
table table.Model
width, height int
}
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.KeyMsg:
switch msg.String() {
case "q", "ctrl+c":
return m, tea.Quit
}
case tea.WindowSizeMsg:
m.height = msg.Height
m.width = msg.Width
}
m.table, cmd = m.table.Update(msg)
return m, cmd
}
func (m model) View() string {
container := lipgloss.NewStyle().
Border(lipgloss.RoundedBorder(), true).
Height(m.height - 2).
Width(m.width - 2).
AlignHorizontal(lipgloss.Center).
AlignVertical(lipgloss.Center)
// Calculate max width for each column:
// - longest item in column
// - longest column title
// - max width is container width / number of columns
columns := m.table.Columns()
rows := m.table.Rows()
for i := range columns {
maxWidth := 0
for _, r := range rows {
if len(r[i]) > maxWidth {
maxWidth = len(r[i])
}
if len(columns[i].Title) > maxWidth {
maxWidth = len(columns[i].Title)
}
if maxWidth > (container.GetWidth() / len(columns)) {
maxWidth = (container.GetWidth() / len(columns)) - 2
}
}
columns[i].Width = maxWidth
}
m.table.SetColumns(columns)
return container.Render(m.table.View())
}
func main() {
p := tea.NewProgram(initialModel(), tea.WithAltScreen())
if _, err := p.Run(); err != nil {
fmt.Printf("Alas, there's been an error: %v", err)
os.Exit(1)
}
}I didnt see anything in the current code for bubbles/table to achieve this but if someone knows of a better way feel free to share. |
Beta Was this translation helpful? Give feedback.
-
|
Hey all, I was interested in this functionality as well, and loosely based on @TheCreatorAMA's code above (thanks!), implemented responsive table width in my It's a bit more advanced since I wanted to declare only specific columns as resizable, and the adjustments are based on the proportion of total window width, but it works well from my tests. I thought this was best done in the bubbles table model instead of the one in my app, since it's generic functionality, and I already had the fork for other improvements. I'm still learning about the best ways of assembling layouts with Bubbletea, so I might decide to change this and you shouldn't depend on my fork, but feel free to copy it if you find it useful. Cheers! |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
I have been trying to make tables responsive. Using the table example, I first wanted to make it stretch to the end of my terminal but I ended up with a table with no right border.
I have tried using
tea.WindowSizeMsgwith various changes to the width but it still doesn't work.So how do I create a table that's fullscreen by default and can resize itself?
Beta Was this translation helpful? Give feedback.
All reactions