Packages
phoenix_duskmoon
9.0.0-rc.1
9.9.2
9.9.1
9.9.0
9.8.0
9.7.1
9.7.0
9.6.4
9.6.3
9.6.2
9.6.1
9.6.0
9.5.4
9.5.3
9.5.2
9.5.1
9.5.0
9.4.3
9.4.2
9.4.1
9.4.0
9.3.0
9.2.0
9.1.4
9.1.3
9.1.1
9.1.1-rc.1
retired
9.0.1
9.0.0-rc.3
9.0.0-rc.2
9.0.0-rc.1
8.0.0
7.2.1
7.2.0
7.1.3
7.1.2
7.1.1
6.3.2
6.3.1
6.3.0
6.2.0
6.1.3
6.1.2
6.1.1
6.1.0
6.0.10
6.0.9
6.0.8
6.0.7
6.0.6
6.0.5
6.0.4
6.0.3
6.0.2
6.0.1
6.0.0
5.2.0-beta.5
5.2.0-beta.4
5.2.0-beta.3
5.2.0-beta.2
5.2.0-beta.1
5.1.0
5.0.6
5.0.5
5.0.4
5.0.3
5.0.2
5.0.1
5.0.0
4.6.6
4.6.5
4.6.4
4.6.3
4.6.2
4.6.1
4.6.0
4.5.2
4.5.1
4.5.0
4.4.4
4.4.3
4.4.2
4.4.1
4.4.0
4.3.2
4.3.1
4.3.0
4.2.0
4.1.1
4.1.0
4.0.0
Duskmoon UI component library for Phoenix LiveView
Current section
Files
Jump to
Current section
Files
lib/phoenix_duskmoon/component/data_display/table.ex
defmodule PhoenixDuskmoon.Component.DataDisplay.Table do
@moduledoc """
Table component for displaying structured data.
Supports sorting, zebra striping, hover effects, bordered layout,
compact mode, and expandable row details.
## Examples
<.dm_table data={@users}>
<:col :let={user} label="Name">{user.name}</:col>
<:col :let={user} label="Email">{user.email}</:col>
</.dm_table>
"""
use Phoenix.Component
@doc """
Generates a table.
## Examples
```heex
<.dm_table data={[
%{
name: "Shmi Skywalker",
portrayal: "Pernilla August (Episodes I-II)"
},
%{
name: "Luke Skywalker",
portrayal: "Mark Hamill (Episodes IV-IX, The Mandalorian, The Book of Boba Fett)"}
]}
>
<:caption>Skywalker House</:caption>
<:col :let={r} label="Name" label_class="text-info" class="text-info">
{r.name}
</:col>
<:col :let={r} label="Portrayal">
{r.portrayal}
</:col>
</.dm_table>
```
"""
@doc type: :component
attr(:id, :any,
default: nil,
doc: "HTML id attribute"
)
attr(:class, :any,
default: nil,
doc: "additional CSS classes"
)
attr(:border, :boolean,
default: false,
doc: "show table borders using table-bordered CSS class"
)
attr(:zebra, :boolean,
default: false,
doc: "show zebra striping"
)
attr(:hover, :boolean,
default: false,
doc: "highlight rows on hover"
)
attr(:compact, :boolean,
default: false,
doc: "make table more compact"
)
attr(:data, :list,
default: [],
doc: """
table data list
"""
)
attr(:rest, :global, doc: "additional HTML attributes for the table element")
attr(:stream, :boolean,
default: false,
doc: "stream data"
)
slot(:caption,
required: false,
doc: """
render a caption of table.
Example
```heex
<:caption>
Table information
</:caption>
```
"""
) do
attr(:id, :any, doc: "table caption id")
attr(:class, :any, doc: "table caption class")
end
slot(:col,
required: false,
doc: """
render a column of table.
Example
```heex
<:col :let={r} label="Name">
{r.name}
</:col>
```
"""
) do
attr(:label, :string, doc: "table column title")
attr(:label_class, :any, doc: "table column title CSS classes")
attr(:class, :any, doc: "table row column class")
end
slot(:expand,
required: false,
doc: """
render a one column row after each row of table.
Example
```heex
<:expand :let={r} label="Name">
<pre>
{r.description}
</pre>
</:expand>
```
"""
) do
attr(:id, :any, doc: "table row expand id")
attr(:class, :any, doc: "table row expand class")
end
def dm_table(assigns) do
assigns = assign(assigns, :col_count, max(length(assigns.col), 1))
~H"""
<table
role="table"
id={@id}
class={[
"table",
@border && "table-bordered",
@zebra && "table-zebra",
@hover && "table-hover",
@compact && "table-compact",
@class,
]}
{@rest}
>
<caption
:for={caption <- @caption}
id={caption[:id]}
class={caption[:class]}
>{render_slot(caption)}</caption>
<thead role="row-group" class="hidden md:table-header-group sticky top-0">
<tr role="row">
<th
:for={col <- @col}
role="columnheader"
scope="col"
class={col[:label_class]}
>{col.label}</th>
</tr>
</thead>
<tbody :if={@stream} role="row-group" id={@id && "#{@id}-stream-body"} phx-update="stream">
<tr
:for={{row_id, row} <- @data}
role="row"
id={row_id}
>
<td
:for={col <- @col}
data-label={col.label}
role="cell"
class={col[:class]}
>{render_slot(col, row)}</td>
</tr>
</tbody>
<tbody :if={!@stream} role="row-group">
<%= for row <- @data do %>
<tr
role="row"
>
<td
:for={col <- @col}
data-label={col.label}
role="cell"
class={col[:class]}
>{render_slot(col, row)}</td>
</tr>
<tr
role="row"
class={[
"table-row-expand",
expand[:class]
]}
:if={@expand != []}
:for={expand <- @expand}
id={expand[:id]}
>
<td
colspan={@col_count}
role="cell"
class="p-0"
>{render_slot(expand, row)}</td>
</tr>
<% end %>
</tbody>
</table>
"""
end
end