PUI. Table
(pui v1.0.0)
Copy Markdown
A styled, stream-aware data table for Phoenix LiveView.
PUI.Table renders the structure and presentation of a data table while the
host application owns data loading, sorting, filtering, pagination, and row
actions. It supports ordinary lists and LiveView stream collections through
the same column and action slots.
Basic usage
<.table id="users" rows={@users}>
<:col :let={user} label="Name">{user.name}</:col>
<:col :let={user} label="Email">{user.email}</:col>
<:action :let={user}>
<.button size="sm" variant="ghost" phx-click="edit" phx-value-id={user.id}>
Edit
</.button>
</:action>
</.table>LiveView streams
Pass a stream directly to rows. The stream item given to the slots is a
{dom_id, item} tuple, matching Phoenix's stream rendering contract. The
default row ID uses the stream DOM ID; provide row_id when the host needs a
different identity function.
<.table id="projects" rows={@streams.projects}>
<:col :let={{_dom_id, project}} label="Project">{project.name}</:col>
<:col :let={{_dom_id, project}} label="Status">{project.status}</:col>
</.table>Customization
Styled tables use PUI's semantic token classes by default. The component
exposes separate class attributes for each rendered part, so an application
can customize the table without replacing its structure. Every part class
attribute defaults to "", so an application that sets all of them owns the
full presentation. A table is plain semantic markup, so write a <table>
directly when PUI's structure is not wanted at all.
<.table
id="invoices"
rows={@invoices}
class="overflow-hidden rounded-xl border"
table_class="w-full text-sm"
header_class="bg-muted"
row_class="border-b last:border-b-0"
cell_class="px-4 py-3"
>
<:col :let={invoice} label="Number">{invoice.number}</:col>
<:col :let={invoice} label="Total" cell_class="text-right">{invoice.total}</:col>
</.table>Attributes
| Name | Type | Default | Description |
|---|---|---|---|
id | string | required | Stable ID for the table body and LiveView stream target |
rows | list or LiveView stream | required | A list of rows or a LiveView stream |
row_id | function | derived | Function receiving a rendered row and returning its DOM ID |
row_click | function | nil | Function receiving a rendered row and returning a phx-click value |
row_item | function | identity | Function mapping a rendered row before it is passed to slots |
action_label | string | "Actions" | Screen-reader label for the action column |
class | string | "" | Classes for the outer overflow wrapper |
caption_class | string | "sr-only" | Classes for the table caption |
table_class | string | "" | Classes for the <table> element |
header_class | string | "" | Classes for the <thead> element |
header_cell_class | string | "" | Classes for each column header cell |
body_class | string | "" | Classes for the <tbody> element |
row_class | string | "" | Classes for each row |
cell_class | string | "" | Classes for each data cell |
action_header_class | string | "" | Classes for the action header cell |
action_cell_class | string | "" | Classes for the action data cell |
action_class | string | "" | Classes for the action cell's inner wrapper |
empty_class | string | "" | Classes for the empty-state cell |
Slots
| Slot | Required | Description |
|---|---|---|
caption | — | Optional table caption |
col | yes | A data column; supports label, class, header_class, and cell_class |
action | — | Optional row actions; receives the rendered row |
empty | — | Empty-state content for ordinary empty lists |
Summary
Functions
Renders a data table from a list or LiveView stream.
Functions
Renders a data table from a list or LiveView stream.
The :col slot receives the row produced by row_item/1. With ordinary
lists this is the original row. With LiveView streams it is a {dom_id, item}
tuple unless row_item maps it to another value.
Attributes
id(:string) (required)rows(:any) (required)row_id(:any) - Defaults tonil.row_click(:any) - Defaults tonil.row_item(:any) - Defaults to&Function.identity/1.action_label(:string) - Defaults to"Actions".class(:string) - Defaults to"".caption_class(:string) - Defaults to"sr-only".table_class(:string) - Defaults to"".header_class(:string) - Defaults to"".header_cell_class(:string) - Defaults to"".body_class(:string) - Defaults to"".row_class(:string) - Defaults to"".cell_class(:string) - Defaults to"".action_header_class(:string) - Defaults to"".action_cell_class(:string) - Defaults to"".action_class(:string) - Defaults to"".empty_class(:string) - Defaults to"".- Global attributes are accepted.
Slots
captioncol(required) - Accepts attributes:label(:string)class(:string)header_class(:string)cell_class(:string)
action- Accepts attributes:class(:string)
empty