Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions pkg/x/m3table/options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package m3table

import (
"github.com/zodimo/go-compose/compose/ui"
"github.com/zodimo/go-compose/compose/ui/unit"
"github.com/zodimo/go-compose/pkg/api"
)

// Column defines the configuration for a single column in the table.
type Column struct {
// Header is an optional composable that defines the column header.
Header api.Composable
// Weight is the flex weight of the column. If greater than 0, the column
// scales proportionally based on its weight.
Weight int
// Width is the fixed width of the column. This is used if Weight is 0.
Width unit.Dp
}

type TableOptions struct {
Modifier ui.Modifier
MinHeaderRowHeight unit.Dp
MinRowHeight unit.Dp
}

type TableOption func(*TableOptions)

func DefaultTableOptions() TableOptions {
return TableOptions{
Modifier: ui.EmptyModifier,
MinHeaderRowHeight: 56, // Material 3 standard data table header row height
MinRowHeight: 52, // Material 3 standard data table row height
}
}

func WithModifier(modifier ui.Modifier) TableOption {
return func(o *TableOptions) {
o.Modifier = modifier
}
}

// WithMinHeaderRowHeight sets the minimum height for the header row.
func WithMinHeaderRowHeight(height unit.Dp) TableOption {
return func(o *TableOptions) {
o.MinHeaderRowHeight = height
}
}

// WithMinRowHeight sets the minimum height for data rows.
func WithMinRowHeight(height unit.Dp) TableOption {
return func(o *TableOptions) {
o.MinRowHeight = height
}
}
90 changes: 90 additions & 0 deletions pkg/x/m3table/table.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package m3table

import (
"github.com/zodimo/go-compose/compose/foundation/layout/box"
"github.com/zodimo/go-compose/compose/foundation/layout/column"
"github.com/zodimo/go-compose/compose/foundation/layout/row"
"github.com/zodimo/go-compose/compose/material3/divider"
"github.com/zodimo/go-compose/compose/ui"
"github.com/zodimo/go-compose/modifiers/size"
"github.com/zodimo/go-compose/modifiers/weight"
"github.com/zodimo/go-compose/pkg/api"
)

// Table constructs a basic material3 table layout given a list of columns,
// the number of data rows, and a factory function to create each cell's content.
func Table(
columns []Column,
rowCount int,
cellContent func(row, col int) api.Composable,
options ...TableOption,
) api.Composable {

opts := DefaultTableOptions()
for _, option := range options {
if option != nil {
option(&opts)
}
}

return func(c api.Composer) api.Composer {
c.StartBlock("Table")

hasHeaders := false
for _, col := range columns {
if col.Header != nil {
hasHeaders = true
break
}
}

c.WithComposable(column.Column(
c.Sequence(
c.When(hasHeaders, func(c api.Composer) api.Composer {
return c.Sequence(
row.Row(
func(c api.Composer) api.Composer {
for i, col := range columns {
c.Key(i, wrapCell(col, col.Header))
}
return c
},
row.WithModifier(size.MinHeight(int(opts.MinHeaderRowHeight))),
),
divider.Divider(),
)(c)
}),
c.Range(rowCount, func(r int) api.Composable {
return row.Row(
func(c api.Composer) api.Composer {
for cIdx, col := range columns {
c.Key(cIdx, wrapCell(col, cellContent(r, cIdx)))
}
return c
},
row.WithModifier(size.MinHeight(int(opts.MinRowHeight))),
)
}),
),
column.WithModifier(opts.Modifier),
))

return c.EndBlock()
}
}

// wrapCell wraps the provided content into a box with proper width modifiers.
func wrapCell(col Column, content api.Composable) api.Composable {
var mod ui.Modifier = ui.EmptyModifier
if col.Weight > 0 {
mod = mod.Then(weight.Weight(col.Weight))
} else if col.Width > 0 {
mod = mod.Then(size.Width(int(col.Width)))
}

if content == nil {
content = func(c api.Composer) api.Composer { return c }
}

return box.Box(content, box.WithModifier(mod))
}
15 changes: 15 additions & 0 deletions test-plan.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Ah, the user asked "What about row height constraints ?"
In `Table`, we currently don't constrain the row height.
Usually a table row in Material 3 has a standard minimum height, or we can add `MinHeight` to `TableOptions` or `RowOptions`.
But `pkg/x/m3table/table.go` uses `row.Row`. We can apply a `MinHeight` modifier to the `row.Row` for both headers and cells.
Let's see if there's a standard Material 3 table row height. The Material 3 spec for Data tables says:
Row height: 52dp
Header row height: 56dp

We can add `MinHeight` modifier to the row.
Wait, let's look at `modifiers/size/constructor.go` to see if we have `MinHeight`.
Yes, `MinHeight(minHeight int) ui.Modifier`.

Let's modify `pkg/x/m3table/table.go` to add a default `MinHeight` to rows, or maybe pass it via `TableOptions`.
Since it's a basic table, maybe we can just hardcode or provide options.
Let's provide `MinRowHeight unit.Dp` and `MinHeaderRowHeight unit.Dp` in `TableOptions`.