DevactionUI.DataTable (devaction_ui v0.7.0)

Copy Markdown View Source

A table for lists that are worked on: sticky header, sortable columns (aria-sort, the server sorts and the table only draws the arrows), optional row selection with a tri-state header checkbox and a bulk bar that appears while something is selected, two densities, and the states of a list: loading, error and empty.

rows is a list, or a stream (stream(socket, :rows, rows)) when the table is long: then the body is a phx-update="stream" and the empty state shows on its own when the stream is empty.

The columns are :col slots (label, key, sortable, class), each given the row with :let. Selection is the browser's: the checkboxes are plain inputs named name[], a hook keeps the header checkbox and the bulk bar in step, and fires input on the table so a form around it hears the change.

selected is the list of row ids ticked when the table is first drawn; after that the browser owns the ticks. A column with no title of its own (the actions of a row) takes hide_label: its label stays for screen readers and is not drawn. The arrows of a sorted header are the sort_asc_icon, sort_desc_icon and sort_none_icon slots (a typographic arrow when empty).

Texts (select_all_label, select_row_label, selected_label with __COUNT__, clear_label) come from the caller, so the library carries no language of its own.

Around the rows: the toolbar slot sits above the table (a search, filter chips, the columns menu) and the footer slot below it, for the range of the page ("1-6 of 33") and a DevactionUI.Pagination. With density_label the toolbar ends with a toggle that switches between the two densities in the browser (density is where it starts; the choice is kept across redraws), its icon the density_icon slot. max_height is a class written in full, so the Tailwind of the app finds it through the @source of this package.

A :col with sticky={:start} (the first column) or sticky={:end} (the actions) stays in view while the table scrolls sideways; in a selectable table the checkbox column is pinned along with the first one. The header is always sticky, and a table with pinned columns gets a shadow on the pinned side only while there is content behind it (the DevactionUI.ScrollArea hook).

loading draws loading_rows rows of skeletons in place of the rows (named once for assistive technology by loading_label, which it needs) and error draws its message, with the error_action slot for a retry button, as an alert; the empty state is the empty slot, or the text empty_text. In a stream the rows stay in the page while one of these shows, hidden.

Variations, which add up:

  • variant is :default (a border and a grey head) or :minimal (no border, a transparent head in sentence case: for a table inside a card or a panel); density={:compact} and striped thin and band the rows.
  • the expanded slot is a detail row opened by a chevron at the start of the row (aria-expanded; the browser toggles it and a redraw keeps it open); expand_label names the button and is required with it.
  • group_by is a function row -> key; consecutive rows with the same key sit under a group row drawn by the group slot, which is given {key, rows}.
  • the tfoot slot is the totals row (give it a <tr>), the footer slot sits below the table.
  • stack turns each row into a card under 640px: the primary column is the title of the card and the other cells carry their column label as a caption.
  • the action slot is the last cell of a row, the ⋯ menu with no box of its own (action_label names the column and is required with it); sticky_actions pins it to the end while the table scrolls sideways.
  • a :col takes align (:start, :center, :end) and mono for figures.
  • Shift+click on a row checkbox ticks every row between it and the last one clicked.

expanded and group_by need rows to be a list: a stream holds one element per row.

Summary

Functions

data_table(assigns)

Attributes

  • id (:string) (required)
  • label (:string) (required) - what the table lists, for assistive technology.
  • rows (:any) (required) - a list, or a LiveView stream for a long table.
  • row_id (:any) - a function: row -> id. Defaults to &DevactionUI.DataTable.default_id/1.
  • sort (:any) - {key, :asc | :desc} or nil. Defaults to nil.

  • on_sort (:string) - the event sent with phx-value-key when a header is clicked. Defaults to nil.
  • variant (:atom) - :minimal has no border and a transparent head, for a table inside a card. Defaults to :default. Must be one of :default, or :minimal.
  • striped (:boolean) - bands every other row. Defaults to false.
  • stack (:boolean) - under 640px each row becomes a card; the primary column is its title. Defaults to false.
  • group_by (:any) - a function: row -> key; consecutive rows with one key sit under a group row (needs a list). Defaults to nil.
  • selectable (:boolean) - Defaults to false.
  • name (:string) - the field name of the row checkboxes (name[]). Defaults to "selected".
  • density (:atom) - the density the table starts in. Defaults to :comfortable. Must be one of :comfortable, or :compact.
  • density_label (:string) - names the density toggle at the end of the toolbar; without it there is no toggle. Defaults to nil.
  • loading (:boolean) - draws skeleton rows instead of the rows. Defaults to false.
  • loading_rows (:integer) - how many skeleton rows. Defaults to 5.
  • loading_label (:string) - what is loading, read once by screen readers; required when loading. Defaults to nil.
  • error (:string) - a message that replaces the rows, drawn as an alert. Defaults to nil.
  • empty_text (:string) - what the empty state says when it has no slot. Defaults to nil.
  • selected (:list) - the ids of the rows ticked at the first draw. Defaults to [].
  • max_height (:string) - a Tailwind class; it is only found if it is written in the app's own sources. Defaults to "max-h-[300px]".
  • sticky_actions (:boolean) - pins the cell of the action slot to the end while the table scrolls sideways. Defaults to false.
  • action_label (:string) - names the column of the action slot for assistive technology; required with it. Defaults to nil.
  • expand_label (:string) - names the chevron that opens a detail row; required with the expanded slot. Defaults to nil.
  • select_all_label (:string) (required)
  • select_row_label (:string) (required)
  • selected_label (:string) (required) - with __COUNT__.
  • clear_label (:string) (required)
  • class (:any) - Defaults to nil.
  • target (:any) - a phx-target (a @myself) when used inside a LiveComponent. Defaults to nil.
  • Global attributes are accepted.

Slots

  • col (required) - Accepts attributes:
    • label (:string) (required)
    • key (:string)
    • sortable (:boolean)
    • hide_label (:boolean) - keep the label for screen readers only.
    • class (:string)
    • primary (:boolean) - the title of the card when the table is a stack.
    • mono (:boolean) - figures in the mono face.
    • align (:atom) - where the text of the column sits; :end for numbers. Must be one of :start, :center, or :end.
    • sticky (:atom) - pins the column to the start (the first column) or the end (the actions) while the table scrolls sideways. Must be one of :start, or :end.
  • sort_asc_icon - the arrow of the column sorted ascending.
  • sort_desc_icon - the arrow of the column sorted descending.
  • sort_none_icon - the arrow of a sortable column that is not sorted.
  • expand_icon - the chevron of the button that opens a detail row (it turns when open).
  • action - the last cell of a row, given the row: the ⋯ menu, with no box of its own.
  • expanded - the detail row under a row, given the row; opened by a chevron.
  • group - the content of a group row, given {key, rows}; required with group_by.
  • tfoot - the totals: a <tr> in the foot of the table.
  • bulk - the actions of the bulk bar.
  • empty - shown when there are no rows.
  • toolbar - above the table: a search, filter chips, a menu of columns.
  • footer - below the table: the range of the page and a pagination.
  • density_icon - the icon of the density toggle.
  • error_action - under the error: a retry button.