A token-styled, slot-driven table and a pagination control.
Both are pure presentation bound to your server state — they never touch
your query. The table renders the chrome (rounded edges from --sk-r, sticky
header, sortable headers, hover, empty state); you own the data and every
cell. Sorting and paging are emitted as phx-click events your LiveView
handles, so it works with Ecto, Flop, raw SQL, an API — and with LiveView
streams for large tables.
It's a superset of CoreComponents.table/1 (same row_id/row_item/
row_click/col/action), so generated phx.gen.live tables drop in.
<.table id="users" rows={@users} sort={@sort} on_sort="sort">
<:col :let={u} field={:name} label="Name" sortable>{u.name}</:col>
<:col :let={u} label="Email">{u.email}</:col>
<:action :let={u}><.button variant="ghost">Edit</.button></:action>
<:empty>No users yet.</:empty>
</.table>
<.pagination page={@page} per_page={@per} total={@total} on_page="page" />
Summary
Functions
A pagination control. Bound to your state — emits on_page with the target
page; your LiveView re-queries. Works for offset paging of any source.
A styled data table. See the module doc.
Functions
A pagination control. Bound to your state — emits on_page with the target
page; your LiveView re-queries. Works for offset paging of any source.
The page-number band is windowed: it always shows the first and last page
with a … gap and siblings pages around the current one, so it stays a fixed
width no matter how many pages there are (1 … 10 11 12 … 21).
Pass per_page_options + on_per_page to render a rows-per-page picker inline
with the "Showing…" count; it pushes the chosen size in the per_page param:
<.pagination
page={@page} per_page={@per} total={@total} on_page="page"
per_page_options={[10, 25, 50]} on_per_page="per_page"
/>
def handle_event("per_page", %{"per_page" => n}, socket) do
{:noreply, socket |> assign(per: String.to_integer(n), page: 1) |> reload()}
endAttributes
id(:string) - stable id (needed for the rows-per-page picker). Defaults to"sk-pagination".page(:integer) (required)per_page(:integer) (required)total(:integer) (required)on_page(:string) (required) - event pushed with phx-value-page.siblings(:integer) - page numbers shown either side of the current page. Defaults to1.per_page_options(:list) - rows-per-page choices (e.g. [10, 25, 50]); renders a picker when set with on_per_page. Defaults tonil.on_per_page(:string) - event pushed (with the new per_page in params) when the rows-per-page picker changes. Defaults tonil.class(:any) - Defaults tonil.
A styled data table. See the module doc.
Attributes
id(:string) (required)rows(:any) (required) - a list, or a LiveView stream.row_id(:any) - row -> DOM id (required for streams). Defaults tonil.row_item(:any) - row -> the item passed to :col :let. Defaults to&Function.identity/1.row_click(:any) - row -> JS, makes the row clickable. Defaults tonil.sort(:map) - %{field: atom, dir: :asc | :desc} for sort indicators. Defaults tonil.on_sort(:string) - event pushed (with field+dir) when a sortable header is clicked. Defaults tonil.class(:any) - Defaults tonil.
Slots
col(required) - Accepts attributes:label(:string)field(:atom)sortable(:boolean)align(:string) - Must be one of"left","center", or"right".class(:any)
action- trailing actions column.empty- shown when rows is empty.