Table
Tables display structured data in rows and columns, with optional striping, row selection, sorting, lazy loading, pagination, filters, and infinite scroll.
| CustomerID | Name | Membership | |
|---|---|---|---|
| 2335 | Alice Brown | [email protected] | Silver |
| 2338 | Bob Johnson | [email protected] | Gold |
| 2342 | Sarah Adams | [email protected] | Gold |
@table.Table(table.Config{
Columns: []table.Column{
{Key: "id", Label: "CustomerID"},
{Key: "name", Label: "Name"},
{Key: "email", Label: "Email"},
{Key: "membership", Label: "Membership"},
},
Rows: rows,
})Striped Table
Set Appearance: table.AppearanceStriped to zebra-stripe the rows.
| CustomerID | Name | Membership | |
|---|---|---|---|
| 2335 | Alice Brown | [email protected] | Silver |
| 2338 | Bob Johnson | [email protected] | Gold |
| 2342 | Sarah Adams | [email protected] | Gold |
| 2345 | Alex Martinez | [email protected] | Gold |
| 2346 | Ryan Thompson | [email protected] | Silver |
| 2349 | Emily Rodriguez | [email protected] | Gold |
@table.Table(table.Config{
Appearance: table.AppearanceStriped,
Columns: columns,
Rows: rows,
})Table with Action
Render an interactive control in a cell via Cell.Component (e.g. button.Button).
| CustomerID | Name | Membership | |
|---|---|---|---|
| 2335 | Alice Brown | [email protected] | |
| 2338 | Bob Johnson | [email protected] | |
| 2342 | Sarah Adams | [email protected] |
@table.Table(table.Config{
Columns: actionColumns(),
Rows: []table.Row{
{ID: "2335", Cells: map[string]table.Cell{
"id": {Text: "2335"},
"name": {Text: "Alice Brown"},
"email": {Text: "[email protected]"},
"action": {Component: tableEditButton()},
}},
},
})Linked Rows with Actions
When a row has both Link and Actions, Goshtoso keeps the row non-interactive and renders the Link in the first data cell. The primary navigation and trailing buttons remain separate keyboard controls.
| CustomerID | Name | Membership | Actions | |
|---|---|---|---|---|
| 2335 | Alice Brown | [email protected] | Silver | |
| 2338 | Bob Johnson | [email protected] | Gold | |
| 2342 | Sarah Adams | [email protected] | Gold |
@table.Table(table.Config{
Columns: columns,
Rows: []table.Row{
{
ID: "2335",
Link: "/customers/2335",
LinkMode: table.LinkFull,
Cells: map[string]table.Cell{
"id": {Text: "2335"},
"name": {Text: "Alice Brown"},
},
Actions: customerActions("2335"),
},
},
})Selectable Rows
Set ShowCheckbox: true to add row-selection controls with a header check-all toggle.
| CustomerID | Name | Membership | ||
|---|---|---|---|---|
| 2335 | Alice Brown | [email protected] | ||
| 2338 | Bob Johnson | [email protected] | ||
| 2342 | Sarah Adams | [email protected] |
@table.Table(table.Config{
ShowCheckbox: true,
Columns: actionColumns(),
Rows: rows,
})Users Table
Compose rich cells with table.ImageCell, badge.Badge, and button.Button.
| User | ID | Member Since | Status | Action |
|---|---|---|---|---|
Alice Brown [email protected] | 2335 | Nov 14, 2021 | Active | |
Bob Johnson [email protected] | 2338 | Aug 20, 2020 | Active | |
Ryan Thompson [email protected] | 2346 | Feb 5, 2022 | Canceled | |
Emily Rodriguez [email protected] | 2349 | Jun 14, 2022 | Active | |
Alex Martinez [email protected] | 2345 | Sep 17, 2018 | Active |
@table.Table(table.Config{
Columns: usersColumns(),
Rows: []table.Row{
{ID: "2335", Cells: map[string]table.Cell{
"user": {Component: table.ImageCell("/.../avatar-8.webp", "Alice Brown", "[email protected]")},
"id": {Text: "2335"},
"since": {Text: "Nov 14, 2021"},
"status": {Component: badge.Badge(badge.Config{Label: "Active", Tone: badge.ToneSuccess, Size: badge.SizeSM})},
"action": {Component: tableEditButton()},
}},
},
})
templ tableEditButton() {
@button.Button(button.WithSize(button.SizeSmall)) {
Edit
}
}Sortable Table (HTMX)
Mark columns Sortable: true and set HTMX.Endpoint. Clicking a header cycles neutral → asc → desc and fetches sorted rows from the server.
CustomerID | Name | Membership | |
|---|---|---|---|
| 2335 | Alice Brown | [email protected] | Silver |
| 2338 | Bob Johnson | [email protected] | Gold |
| 2342 | Sarah Adams | [email protected] | Gold |
| 2345 | Alex Martinez | [email protected] | Gold |
| 2346 | Ryan Thompson | [email protected] | Silver |
| 2349 | Emily Rodriguez | [email protected] | Gold |
@table.Table(table.Config{
ID: "sortable-table",
HTMX: &table.HTMXConfig{Endpoint: "/api/components/table/rows?variant=sortable&per_page=6"},
SortBy: "id",
SortDir: table.SortAsc,
Columns: []table.Column{
{Key: "id", Label: "CustomerID", Sortable: true},
{Key: "name", Label: "Name", Sortable: true},
{Key: "email", Label: "Email"},
{Key: "membership", Label: "Membership", Sortable: true},
},
Rows: rows,
})Lazy-Loaded Table
Set LazyLoad: true to render a loading tbody, then choose when HTMX fetches rows. The default trigger is page load; this example waits for a button click.
The table renders its headers first. Rows are fetched only after you request them.
| CustomerID | Name | Membership | |
|---|---|---|---|
Loading... | |||
@table.Table(table.Config{
ID: "lazy-table",
HTMX: &table.HTMXConfig{Endpoint: "/api/components/table/rows?variant=lazy"},
LazyLoad: true,
LazyTrigger: "click from:#load-lazy-table",
Columns: columns,
})Paginated Table
Pass a Pagination config; Prev/Next and page links swap the tbody and paginator via HTMX OOB.
CustomerID | Name | Membership | |
|---|---|---|---|
| 2335 | Alice Brown | [email protected] | Silver |
| 2338 | Bob Johnson | [email protected] | Gold |
| 2342 | Sarah Adams | [email protected] | Gold |
@table.Table(table.Config{
ID: "paginated-table",
HTMX: &table.HTMXConfig{Endpoint: "/api/components/table/rows"},
Columns: sortableColumns(),
Rows: pageRows(1),
Pagination: &table.PaginationConfig{CurrentPage: 1, TotalPages: 4, PerPage: 3},
})Filtered Table
Add a Filters config with search/select/toggle filters. The bar variant renders a collapsible bordered block.
CustomerID | Name | Membership | |
|---|---|---|---|
| 2335 | Alice Brown | [email protected] | Silver |
| 2338 | Bob Johnson | [email protected] | Gold |
| 2342 | Sarah Adams | [email protected] | Gold |
@table.Table(table.Config{
ID: "filtered-table",
HTMX: &table.HTMXConfig{Endpoint: "/api/components/table/rows"},
Columns: sortableColumns(),
Rows: pageRows(1),
Pagination: &table.PaginationConfig{CurrentPage: 1, TotalPages: 4, PerPage: 3},
Filters: &table.FilterConfig{
Collapsible: true,
InitiallyExpanded: true,
Filters: []table.Filter{
{Key: "search", Label: "Search", Type: table.FilterSearch, Placeholder: "Search by name or email..."},
{Key: "membership", Label: "Membership", Type: table.FilterSelect, Options: memberships},
},
},
})Inline Filter Appearance
Set Filters.Appearance: table.FilterAppearanceInline for the same controls without the bordered block or collapsible toggle — suited to modal bodies and toolbar strips.
| CustomerID | Name | Membership | |
|---|---|---|---|
| 2335 | Alice Brown | [email protected] | Silver |
| 2338 | Bob Johnson | [email protected] | Gold |
| 2342 | Sarah Adams | [email protected] | Gold |
Filters: &table.FilterConfig{
Appearance: table.FilterAppearanceInline,
Filters: []table.Filter{
{Key: "search", Type: table.FilterSearch, Placeholder: "Search…"},
{Key: "membership", Type: table.FilterSelect, Options: memberships},
},
}Infinite Scroll Table
Use Pagination.Mode: table.PaginationInfiniteScroll. By default the sentinel watches the page scroller; set Pagination.ContainerHeight only when the table needs its own capped scroll area.
| CustomerID | Name | Membership | |
|---|---|---|---|
| 2335 | Alice Brown | [email protected] | Silver |
| 2338 | Bob Johnson | [email protected] | Gold |
| 2342 | Sarah Adams | [email protected] | Gold |
@table.Table(table.Config{
ID: "infinite-table",
HTMX: &table.HTMXConfig{Endpoint: "/api/components/table/rows?variant=infinite"},
Columns: columns,
Rows: initialRows,
Pagination: &table.PaginationConfig{
Mode: table.PaginationInfiniteScroll,
CurrentPage: 1,
PerPage: 3,
HasMore: true,
ContainerHeight: "300px",
},
})Go API
v0.2.7The examples above cover behavior and composition. pkg.go.dev is the canonical reference for exported types, functions, methods, and Go documentation.
github.com/araihu/goshtoso/components/table