Table layout and presentation DSL

v0.0.1

The layout, empty_state, error_state and presentation sections of a resource's table block set the header, footer and notices around the table, what an empty or failed table says, and which template, UI adapter and theme draw it.

layout

The layout section has no options of its own. It holds the header, footer and notice entities, which draw the chrome around the table.

header

A title and description drawn above the toolbar. It sits at mishka_gervaz.table.layout.header.

OptionTypeDefaultDescription
titleString.t | (-> any) | (any -> any)noneHeader title. String, fn -> _ end, or fn state -> _ end.
descriptionString.t | (-> any) | (any -> any)noneHeader description. String, fn -> _ end, or fn state -> _ end.
iconString.tnoneHeroicon name (e.g., "hero-document-text").
classString.tnoneCSS classes for the header wrapper.
visibleboolean | (any -> any)trueStatic or dynamic visibility. fn state -> boolean() end.
restrictedboolean | (any -> any)falseRestrict to master users. true or fn state -> boolean() end.
render(any -> any) | (any, any -> any)noneCustom HEEx render. fn assigns -> ~H"..." end or fn assigns, state -> ~H"..." end.
extramap%{}Additional template-specific options. The value is compiled into the config, but no built-in template or handler reads it.

footer

Static content drawn below the pagination. It sits at mishka_gervaz.table.layout.footer.

OptionTypeDefaultDescription
contentString.t | (-> any) | (any -> any)noneFooter content. String, fn -> _ end, or fn state -> _ end.
classString.tnoneCSS classes for the footer wrapper.
visibleboolean | (any -> any)trueStatic or dynamic visibility. fn state -> boolean() end.
restrictedboolean | (any -> any)falseRestrict to master users. true or fn state -> boolean() end.
render(any -> any) | (any, any -> any)noneCustom HEEx render. fn assigns -> ~H"..." end or fn assigns, state -> ~H"..." end.
extramap%{}Additional template-specific options. The value is compiled into the config, but no built-in template or handler reads it.

notice

A static alert or banner with a position and an optional binding. It sits at mishka_gervaz.table.layout.notice.

Call: notice name

Arguments:

ArgumentTypeDefaultDescription
nameatomnoneRequired. Unique notice identifier (used for dismiss tracking).

Options:

OptionTypeDefaultDescription
positionany:table_topWhere the notice is drawn. Valid atoms and tuples are listed below the table. The default is :table_top.
type:info | :warning | :error | :success | :neutral:infoVisual style: :info, :warning, :error, :success, or :neutral.
titleString.t | (-> any) | (any -> any)noneNotice title. String, fn -> _ end, or fn state -> _ end.
contentString.t | (-> any) | (any -> any)noneNotice body. String, fn -> _ end, or fn state -> _ end.
iconString.tnoneHeroicon name.
dismissiblebooleanfalseLets the reader close the notice. Gervaz tracks dismissal by notice name.
bind_tonil | :no_results | :has_filters | :has_selection | :loading | :error | :archived_viewnoneDraws the notice only while a condition holds. See the list below the table. Combined with show_when using AND.
show_when(any -> any)noneCustom predicate fn state -> boolean() end. Combined with bind_to (AND).
visibleboolean | (any -> any)trueStatic or dynamic visibility. fn state -> boolean() end.
restrictedboolean | (any -> any)falseRestrict to master users. true or fn state -> boolean() end.
render(any -> any) | (any, any -> any)noneCustom HEEx render. fn assigns -> ~H"..." end or fn assigns, state -> ~H"..." end.

Valid position values:

PositionWhere the notice is drawn
:table_topAbove everything in the table region. The default.
:before_header, :after_headerAround the table header.
:before_filters, :after_filtersAround the filter bar.
:before_bulk_actions, :after_bulk_actionsAround the bulk action bar.
:before_table, :after_tableAround the table itself.
:before_pagination, :after_paginationAround the pagination row.
:table_bottomThe last slot in the table region.
:empty_stateThe empty-state area. The built-in template draws it whether or not the table has rows.
{:before_column, name}, {:after_column, name}Gervaz validates these, and no built-in template draws a notice there.

Valid bind_to values:

ValueThe notice shows while
:no_resultsThe stream is empty after a load.
:has_filtersAny filter has a value.
:has_selectionAny row is selected.
:loadingThe table is loading.
:errorThe load returned an error.
:archived_viewThe reader is viewing archived records.

notice ui

Classes for the notice. It sits at mishka_gervaz.table.layout.notice.ui.

OptionTypeDefaultDescription
classString.tnoneCSS classes for the notice wrapper.
extramap%{}Additional template-specific options. The value is compiled into the config, but no built-in template or handler reads it.

empty_state

What the table shows when there are no records. Declare it inline or as a block. It sits at mishka_gervaz.table.empty_state.

OptionTypeDefaultDescription
messageString.t"No records found"Empty state message.
iconString.tnoneIcon identifier.
action_labelString.tnoneLabel of a call-to-action link drawn under the message. Give action_label and action_path. action_icon is optional.
action_pathString.tnoneCall-to-action button path.
action_iconString.tnoneCall-to-action button icon.

error_state

What the table shows when a load fails. Declare it inline or as a block. It sits at mishka_gervaz.table.error_state.

OptionTypeDefaultDescription
messageString.t"Error loading data"Error message. The value is compiled into the config, but no built-in template or handler reads it. The built-in templates do not draw the error state from it.
iconString.tnoneIcon identifier. The value is compiled into the config, but no built-in template or handler reads it. The built-in templates do not draw the error state from it.
retry_labelString.t"Retry"Retry button label. The value is compiled into the config, but no built-in template or handler reads it. The built-in templates do not draw the error state from it.

presentation

Picks the template, the UI adapter, the features and the filter mode. It sits at mishka_gervaz.table.presentation.

OptionTypeDefaultDescription
filter_mode:inline | :sidebar | :modal | :drawer:inlineWhere the filter bar draws. :inline draws it above the table, and :sidebar draws a side column. :modal and :drawer draw a Filters button whose toggle_filters event has no handler, so they open nothing. Gervaz ignores this option when the table declares filter_groups.
templateatom | moduleMishkaGervaz.Table.Templates.TableThe template module that arranges the table. Built in: MishkaGervaz.Table.Templates.Table (the default) and MishkaGervaz.Table.Templates.MediaGallery.
switchable_templateslist(atom | module)[]Templates the reader can switch between. With two or more, the template switcher shows. An empty list turns switching off.
template_optionskeyword[]Options passed to the template. The Table template reads :striped and :hoverable. MediaGallery reads :columns, :overlay_action, :primary_action and :class. A template ignores a key it does not read.
keep_loaded_recordsbooleanfalseKeeps every loaded page in state.loaded_records for a template that groups rows under headings and so cannot draw from a stream. It holds the loaded rows in the LiveView's memory, so turn it on only for a grouped template.
features:all | list(:sort | :filter | :select | :bulk_actions | :paginate | :export | :expand | :reorder | :inline_edit):all:all uses the union of what the template and every switchable template support, minus :paginate when the table has no pagination. A list narrows it, and [] turns everything off. Accepted: :sort, :filter, :select, :bulk_actions, :paginate, :export, :expand, :reorder and :inline_edit. The built-in templates act on :sort, :filter, :select, :bulk_actions, :paginate and :expand only.
ui_adapteratom | moduleMishkaGervaz.UIAdapters.TailwindThe UI adapter module that draws buttons, inputs, badges and cells. MishkaGervaz.UIAdapters.Tailwind is the default. Build your own with use MishkaGervaz.Behaviours.UIAdapter.
ui_adapter_optskeyword[]Options for the adapter. With ui_adapter MishkaGervaz.UIAdapters.Dynamic, Gervaz builds <Resource>.GervazUIAdapter from :site (default "Global"), :fallback, :component_renderer and :module_resolver. Gervaz checks Dynamic first, so :component_module is ignored with it. With :component_module and another adapter, Gervaz builds <Resource>.GervazUIAdapter that calls the matching functions of that module, using :fallback, :nested_components, :module_prefix and :component_prefix.

theme

Theme classes. It sits at mishka_gervaz.table.presentation.theme.

OptionTypeDefaultDescription
header_classString.tnoneHeader row CSS classes.
row_classString.tnoneData row CSS classes.
border_classString.tnoneBorder CSS classes. The value is compiled into the config, but no built-in template or handler reads it.
extramap%{}Template-specific theming options. The value is compiled into the config, but no built-in template or handler reads it.

responsive

Responsive settings. It sits at mishka_gervaz.table.presentation.responsive.

OptionTypeDefaultDescription
hide_on_mobilelist(atom)[]Columns to hide on mobile. The value is compiled into the config, but no built-in template or handler reads it.
hide_on_tabletlist(atom)[]Columns to hide on tablet. The value is compiled into the config, but no built-in template or handler reads it.
mobile_layout:cards | :stackednoneLayout mode on mobile. The value is compiled into the config, but no built-in template or handler reads it.