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

NameTypeDefaultDescription
idstringrequiredStable ID for the table body and LiveView stream target
rowslist or LiveView streamrequiredA list of rows or a LiveView stream
row_idfunctionderivedFunction receiving a rendered row and returning its DOM ID
row_clickfunctionnilFunction receiving a rendered row and returning a phx-click value
row_itemfunctionidentityFunction mapping a rendered row before it is passed to slots
action_labelstring"Actions"Screen-reader label for the action column
classstring""Classes for the outer overflow wrapper
caption_classstring"sr-only"Classes for the table caption
table_classstring""Classes for the <table> element
header_classstring""Classes for the <thead> element
header_cell_classstring""Classes for each column header cell
body_classstring""Classes for the <tbody> element
row_classstring""Classes for each row
cell_classstring""Classes for each data cell
action_header_classstring""Classes for the action header cell
action_cell_classstring""Classes for the action data cell
action_classstring""Classes for the action cell's inner wrapper
empty_classstring""Classes for the empty-state cell

Slots

SlotRequiredDescription
captionOptional table caption
colyesA data column; supports label, class, header_class, and cell_class
actionOptional row actions; receives the rendered row
emptyEmpty-state content for ordinary empty lists

Summary

Functions

Renders a data table from a list or LiveView stream.

Functions

table(assigns)

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 to nil.
  • row_click (:any) - Defaults to nil.
  • 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

  • caption
  • col (required) - Accepts attributes:
    • label (:string)
    • class (:string)
    • header_class (:string)
    • cell_class (:string)
  • action - Accepts attributes:
    • class (:string)
  • empty