# `PhiaUi.Components.DataTable`
[🔗](https://github.com/charlenopires/PhiaUI/blob/v0.1.17/lib/phia_ui/components/data/data_table.ex#L1)

All-in-one declarative table — define columns once, render everything.

Unlike the composable `Table` primitive (where you manually write thead/tbody
rows), `DataTable` generates the full table structure from a `:rows` list and
named `:column` slots. This makes common tables fast to build with minimal
boilerplate.

For advanced use cases (streams, row selection, pagination, column toggle)
use `DataGrid` instead.

## Sub-components

| Function            | Used as           | Purpose                            |
|---------------------|-------------------|------------------------------------|
| `data_table/1`      | Component         | Outer table + header + body        |
| `:column` slot      | `<:column>`       | Column definition with inner_block |

## Example

    <.data_table
      rows={@users}
      sort_key={@sort_key}
      sort_dir={@sort_dir}
      on_sort="sort"
      striped
    >
      <:column key="name" label="Name" sortable :let={user}>
        <span class="font-medium">{user.name}</span>
      </:column>
      <:column key="email" label="Email" sortable :let={user}>
        {user.email}
      </:column>
      <:column key="role" label="Role" align={:center} :let={user}>
        <.badge variant={:secondary}>{user.role}</.badge>
      </:column>
      <:action :let={user}>
        <.button variant={:ghost} size={:sm} phx-click="edit" phx-value-id={user.id}>
          Edit
        </.button>
      </:action>
    </.data_table>

## Sort events

Sortable column headers fire the `on_sort` event with `phx-value-key` and
`phx-value-dir` (the **next** direction: `"asc"`, `"desc"`, or `"none"`):

    def handle_event("sort", %{"key" => key, "dir" => dir}, socket) do
      {:noreply, assign(socket, sort_key: key, sort_dir: String.to_existing_atom(dir))}
    end

# `data_table`

Renders a complete table from `rows` and `:column` slot definitions.

Column headers are generated from `:column` slot attrs (`label`, `sortable`,
`align`). Each body row is built by iterating `rows` and calling
`render_slot(col, row)` for each column — the slot's `:let` binding receives
the row map/struct.

## Example

    <.data_table rows={@products} empty_message="No products yet">
      <:column key="name" label="Product" :let={p}>{p.name}</:column>
      <:column key="price" label="Price" align={:right} :let={p}>
        ${p.price}
      </:column>
    </.data_table>

## Attributes

* `rows` (`:list`) (required) - List of maps or structs to render — one row per element.
* `row_id` (`:any`) - Optional function `fn row -> id end` to extract a stable row identifier.
  Not used directly in the render but available for LiveView stream integration.

  Defaults to `nil`.
* `sort_key` (`:string`) - Key of the currently sorted column. Matches the `key` attr on `:column` slots. Defaults to `nil`.
* `sort_dir` (`:atom`) - Current sort direction. `:none` shows the unsorted double-chevron icon. Defaults to `:none`. Must be one of `:none`, `:asc`, or `:desc`.
* `on_sort` (`:string`) - `phx-click` event fired when a sortable column header is clicked. Receives
  `phx-value-key` (column key) and `phx-value-dir` (next direction string).

  Defaults to `"sort"`.
* `striped` (`:boolean`) - When `true`, alternating rows receive a subtle `bg-muted/30` background. Defaults to `false`.
* `empty_message` (`:string`) - Text displayed when `rows` is an empty list. Defaults to `"No data"`.
* `class` (`:string`) - Additional CSS classes for the outer wrapper div. Defaults to `nil`.
## Slots

* `column` - Accepts attributes:

  * `key` (`:string`) (required)
  * `label` (`:string`) (required)
  * `sortable` (`:boolean`)
  * `align` (`:atom`) - Must be one of `:left`, `:right`, or `:center`.
  * `width` (`:string`)
* `action` - Optional per-row action cell appended as the last column. The slot
  receives each row via `:let`:

      <:action :let={user}>
        <.button phx-click="delete" phx-value-id={user.id}>Delete</.button>
      </:action>

---

*Consult [api-reference.md](api-reference.md) for complete listing*
