charmbracelet / bubbles

TUI components for Bubble Tea 🫧
MIT License
5.24k stars 247 forks source link

Table add WithStyleFunc to customize cell styling #504

Closed KevM closed 3 months ago

KevM commented 4 months ago

This change ports a customization from lipgloss's table to bubbles' table.

Option WithStyleFunc

This option lets the user set a style selection func during table creation.

type TableStyleFunc func(row, col int, value string) lipgloss.Style

This func allows the user to customize the style that will appear for each row and col.

Example

It is tricky to commit a demo due to the examples for bubbles being in the bubbletea repository but this diff to the table example creates the result below where the Mexican row is customized to include the flag colors of Mexico.

Example Diff

diff --git a/examples/table/main.go b/examples/table/main.go
index 76736f3..23443ee 100644
--- a/examples/table/main.go
+++ b/examples/table/main.go
@@ -157,13 +157,6 @@ func main() {
                {"100", "Montreal", "Canada", "4,276,526"},
        }

-       t := table.New(
-               table.WithColumns(columns),
-               table.WithRows(rows),
-               table.WithFocused(true),
-               table.WithHeight(7),
-       )
-
        s := table.DefaultStyles()
        s.Header = s.Header.
                BorderStyle(lipgloss.NormalBorder()).
@@ -174,7 +167,29 @@ func main() {
                Foreground(lipgloss.Color("229")).
                Background(lipgloss.Color("57")).
                Bold(false)
-       t.SetStyles(s)
+
+       t := table.New(
+               table.WithColumns(columns),
+               table.WithRows(rows),
+               table.WithFocused(true),
+               table.WithHeight(7),
+               table.WithStyles(s),
+               table.WithStyleFunc(func(row, col int, value string) lipgloss.Style {
+                       if row == 5 {
+                               if col == 1 {
+                                       return s.Cell.Copy().Background(lipgloss.Color("#006341"))
+                               } else if col == 2 {
+                                       return s.Cell.Copy().Background(lipgloss.Color("#FFFFFF"))
+                               } else if col == 3 {
+                                       return s.Cell.Copy().Background(lipgloss.Color("#C8102E"))
+                               } else {
+                                       return s.Cell
+                               }
+                       }
+
+                       return s.Cell
+               }),
+       )

image

Why

I am using the table component and wish to customize the cell look based on the column and the content of the value being displayed. It would be nice to have a struct representing the Cell data as a placeholder for this sort of thing but that would be a much bigger and breaking change.

Cavets

Selected styling seems to be overridden by my customization. This is what the selected Mexico row looks like:

image

felipeospina21 commented 3 months ago

I was looking for a way to do this, the proposed implementation looks really good, can't wait for it to be merged.

KevM commented 3 months ago

I was looking for a way to do this, the proposed implementation looks really good, can't wait for it to be merged.

I bet @maaslalani will get to it soon. I believe they are catching up from some time off.

maaslalani commented 3 months ago

Hey @KevM, yes this looks great! Will take a look.

KevM commented 3 months ago

I fixed the lint issue by using their suggestion.

maaslalani commented 3 months ago

Hey @KevM, thanks so much for this! This will be great in the meantime before we swap out the entire implementation for lipgloss.Table which should keep a similar API of WithStyleFunc.