Data table with children-based rows for efficient diffing.
Tables support two ways to populate rows:
Rich composition using table_row and cell children for
custom cell content (buttons, icons, any widget):
table "users", columns: cols do
for user <- users do
table_row user.id do
cell "name", text(user.name)
cell "actions", button("del", "Delete")
end
end
endData shorthand using the rows: prop for text-only tables:
table "users", columns: cols, rows: dataThese two approaches are mutually exclusive: setting rows:
and providing do-block children in the same table raises an error.
Props
| Name | Type | Default | Description |
|---|---|---|---|
columns | [map()] | nil | Column definitions. Each map requires a :key (string or atom, consistent across all columns). Optional: :label, :width, :sortable, :align. |
rows | [map()] | nil | Data shorthand for text-only tables. List of maps with keys matching column :key values. Each map should include an :id key for stable row identity. |
header | boolean() | nil | Show header row. Default: true. |
width | :fill | :shrink | {:fill_portion, pos_integer()} | number() | nil | Table width. Default: fill. |
height | :fill | :shrink | {:fill_portion, pos_integer()} | number() | nil | Table height. Wraps in a scrollable when set. |
padding | number() | {number(), number()} | %Plushie.Type.Padding{} | nil | Cell internal padding. |
sort_by | String.t() | atom() | nil | Key of the currently sorted column. |
sort_order | :asc | :desc | nil | Current sort direction: :asc or :desc. |
separator | number() | nil | Divider line thickness in pixels. Set to 0.0 to hide. |
separator_color | String.t() | nil | Divider line color. |
header_text_size | number() | nil | Text size for auto-generated header labels. |
row_text_size | number() | nil | Text size for data shorthand auto-generated cells. |
event_rate | integer() | nil | Max events per second for coalescable events. |
a11y | %Plushie.Type.A11y{} | map() | keyword() | %{role: :table} | Accessibility annotations. |
Events
| Event | Type | Description |
|---|---|---|
:sort | value: String.t() | atom() | Column key when a sortable header is clicked. App handles reordering. |
Summary
Functions
Accessibility annotations.
Converts this widget struct to a ui_node() map.
Column definitions. Each map requires a :key (string or atom, consistent across all columns). Optional: :label, :width, :sortable, :align.
Max events per second for coalescable events.
Appends multiple children to the widget.
Show header row. Default: true.
Text size for auto-generated header labels.
Table height. Wraps in a scrollable when set.
Creates a new widget struct with the given ID and keyword options.
Cell internal padding.
Appends a child to the widget.
Text size for data shorthand auto-generated cells.
Data shorthand for text-only tables. List of maps with keys matching column :key values. Each map should include an :id key for stable row identity.
Divider line thickness in pixels. Set to 0.0 to hide.
Divider line color.
Key of the currently sorted column.
Current sort direction: :asc or :desc.
Creates a :table widget.
Table width. Default: fill.
Applies keyword options to an existing widget struct.
Types
@type option() :: (((((((((((({:columns, [map()]} | {:rows, [map()]}) | {:header, boolean()}) | {:width, :fill | :shrink | {:fill_portion, pos_integer()} | number()}) | {:height, :fill | :shrink | {:fill_portion, pos_integer()} | number()}) | {:padding, number() | {number(), number()} | %Plushie.Type.Padding{ bottom: term(), left: term(), right: term(), top: term() }}) | {:sort_by, String.t() | atom()}) | {:sort_order, :asc | :desc}) | {:separator, number()}) | {:separator_color, atom() | String.t() | map()}) | {:header_text_size, number()}) | {:row_text_size, number()}) | {:event_rate, integer()}) | {:a11y, %Plushie.Type.A11y{ active_descendant: term(), busy: term(), described_by: term(), description: term(), disabled: term(), error_message: term(), expanded: term(), has_popup: term(), hidden: term(), invalid: term(), label: term(), label_from: term(), labelled_by: term(), level: term(), live: term(), mnemonic: term(), modal: term(), orientation: term(), position_in_set: term(), radio_group: term(), read_only: term(), required: term(), role: term(), selected: term(), size_of_set: term(), toggled: term(), value: term() } | map() | keyword()}
@type t() :: %Plushie.Widget.Table{ a11y: (%Plushie.Type.A11y{ active_descendant: term(), busy: term(), described_by: term(), description: term(), disabled: term(), error_message: term(), expanded: term(), has_popup: term(), hidden: term(), invalid: term(), label: term(), label_from: term(), labelled_by: term(), level: term(), live: term(), mnemonic: term(), modal: term(), orientation: term(), position_in_set: term(), radio_group: term(), read_only: term(), required: term(), role: term(), selected: term(), size_of_set: term(), toggled: term(), value: term() } | map() | keyword()) | Plushie.Animation.Transition.t() | Plushie.Animation.Spring.t() | Plushie.Animation.Sequence.t() | nil, children: [Plushie.Widget.ui_node()], columns: [map()] | Plushie.Animation.Transition.t() | Plushie.Animation.Spring.t() | Plushie.Animation.Sequence.t() | nil, event_rate: integer() | Plushie.Animation.Transition.t() | Plushie.Animation.Spring.t() | Plushie.Animation.Sequence.t() | nil, header: boolean() | Plushie.Animation.Transition.t() | Plushie.Animation.Spring.t() | Plushie.Animation.Sequence.t() | nil, header_text_size: number() | Plushie.Animation.Transition.t() | Plushie.Animation.Spring.t() | Plushie.Animation.Sequence.t() | nil, height: (:fill | :shrink | {:fill_portion, pos_integer()} | number()) | Plushie.Animation.Transition.t() | Plushie.Animation.Spring.t() | Plushie.Animation.Sequence.t() | nil, id: String.t(), padding: (number() | {number(), number()} | %Plushie.Type.Padding{ bottom: term(), left: term(), right: term(), top: term() }) | Plushie.Animation.Transition.t() | Plushie.Animation.Spring.t() | Plushie.Animation.Sequence.t() | nil, row_text_size: number() | Plushie.Animation.Transition.t() | Plushie.Animation.Spring.t() | Plushie.Animation.Sequence.t() | nil, rows: [map()] | Plushie.Animation.Transition.t() | Plushie.Animation.Spring.t() | Plushie.Animation.Sequence.t() | nil, separator: number() | Plushie.Animation.Transition.t() | Plushie.Animation.Spring.t() | Plushie.Animation.Sequence.t() | nil, separator_color: String.t() | Plushie.Animation.Transition.t() | Plushie.Animation.Spring.t() | Plushie.Animation.Sequence.t() | nil, sort_by: (String.t() | atom()) | Plushie.Animation.Transition.t() | Plushie.Animation.Spring.t() | Plushie.Animation.Sequence.t() | nil, sort_order: (:asc | :desc) | Plushie.Animation.Transition.t() | Plushie.Animation.Spring.t() | Plushie.Animation.Sequence.t() | nil, width: (:fill | :shrink | {:fill_portion, pos_integer()} | number()) | Plushie.Animation.Transition.t() | Plushie.Animation.Spring.t() | Plushie.Animation.Sequence.t() | nil }
Functions
@spec a11y( widget :: t(), value :: (%Plushie.Type.A11y{ active_descendant: term(), busy: term(), described_by: term(), description: term(), disabled: term(), error_message: term(), expanded: term(), has_popup: term(), hidden: term(), invalid: term(), label: term(), label_from: term(), labelled_by: term(), level: term(), live: term(), mnemonic: term(), modal: term(), orientation: term(), position_in_set: term(), radio_group: term(), read_only: term(), required: term(), role: term(), selected: term(), size_of_set: term(), toggled: term(), value: term() } | map() | keyword()) | nil ) :: t()
Accessibility annotations.
Accepts %Plushie.Type.A11y{} | map() | keyword().
@spec build(widget :: t()) :: Plushie.Widget.ui_node()
Converts this widget struct to a ui_node() map.
Column definitions. Each map requires a :key (string or atom, consistent across all columns). Optional: :label, :width, :sortable, :align.
Accepts [map()].
Max events per second for coalescable events.
Accepts integer().
@spec extend(widget :: t(), children :: [Plushie.Widget.child()]) :: t()
Appends multiple children to the widget.
Show header row. Default: true.
Accepts boolean().
Text size for auto-generated header labels.
Accepts number().
@spec height( widget :: t(), value :: (:fill | :shrink | {:fill_portion, pos_integer()} | number()) | nil ) :: t()
Table height. Wraps in a scrollable when set.
Accepts :fill | :shrink | {:fill_portion, pos_integer()} | number().
Creates a new widget struct with the given ID and keyword options.
@spec padding( widget :: t(), value :: (number() | {number(), number()} | %Plushie.Type.Padding{ bottom: term(), left: term(), right: term(), top: term() }) | nil ) :: t()
Cell internal padding.
Accepts number() | {number(), number()} | %Plushie.Type.Padding{}.
@spec push(widget :: t(), child :: Plushie.Widget.child()) :: t()
Appends a child to the widget.
Text size for data shorthand auto-generated cells.
Accepts number().
Data shorthand for text-only tables. List of maps with keys matching column :key values. Each map should include an :id key for stable row identity.
Accepts [map()].
Divider line thickness in pixels. Set to 0.0 to hide.
Accepts number().
Divider line color.
Accepts String.t().
Key of the currently sorted column.
Accepts String.t() | atom().
Current sort direction: :asc or :desc.
Accepts :asc | :desc.
Creates a :table widget.
Shorthand for new/2. Import this macro to use the widget name
directly in view functions:
import Plushie.Widget.Table, only: [table: 2]
table("my-id", prop: value)
@spec width( widget :: t(), value :: (:fill | :shrink | {:fill_portion, pos_integer()} | number()) | nil ) :: t()
Table width. Default: fill.
Accepts :fill | :shrink | {:fill_portion, pos_integer()} | number().
Applies keyword options to an existing widget struct.