Aurora.Uix.Layout.Blueprint (Aurora UIX v0.1.0)
Comprehensive layout configuration system for dynamic UI generation.
Provides DSL macros for defining declarative, nested, and flexible UI structure for Phoenix LiveView. Supports compile-time layout generation and field arrangement for index, form, and show views.
Layout Hierarchy
- Container Layouts: Index, Form, Show
- Sub-Layouts: Inline, Stacked, Group, Sections, Section
Layout Containers
- Index: Horizontal field arrangement
- Form: Editable field layout
- Show: Read-only field display
Sub-Layout Types
inline: Horizontal field groupingstacked: Vertical field arrangementgroup: Visually segmented fieldssections: Tab-like field organizationsection: Tab contents
Layout Tree Element Structure
Internally, each layout is represented by a list of maps (called "paths"), where each entry contains the following keys:
:tag(atom): The layout command. Possible values include:- Container commands:
:index,:form,:show - Sub-layout commands:
:stacked,:group,:inline,:sectionsandsection
- Container commands:
:name(atom): For container layouts (:index,:form, and:show), this key is required and holds the resource configuration name to which the layout applies. For sub-layout commands, this key is not required.:state(atom): Indicates the beginning (:start) or ending (:end) of a layout block.:opts(keyword list): Contains additional options for customizing the layout (for example, UI overrides such as field length or custom renderers).:config(tuple or map): Holds specific configuration data:- For field lists:
{:fields, fields}wherefieldsis a list of field identifiers. - For groups:
{:title, "Group Title"}. - For sections:
{:title, "Section Title"}or other configuration as needed. - Other commands may store custom configuration information here.
- For field lists:
Usage Examples
Basic Usage
The simplest usage creates an index layout for listing resources and a default form layout containing all enabled fields:
defmodule ProductViews do
alias MyApp.Inventory
alias MyApp.Inventory.Product
auix_resource_metadata(:product, context: Inventory, schema: Product)
auix_create_ui
endCustom Layout for Index and Form
Customize the index view to display only selected columns, and define a form layout with an inline group of fields:
defmodule ProductViews do
alias MyApp.Inventory
alias MyApp.Inventory.Product
auix_resource_metadata(:product, context: Inventory, schema: Product)
auix_create_ui do
index_columns :product, [:reference, :name]
edit_layout :product do
inline [:reference, :name, :description]
end
end
endUsing Sub-Layouts in Form and Show
Within form and show containers, structure the UI using sub-layout commands such as stacked, group, and inline:
defmodule ProductViews do
alias MyApp.Inventory
alias MyApp.Inventory.Product
auix_resource_metadata(:product, context: Inventory, schema: Product)
auix_create_ui do
edit_layout :product do
inline do
group "Identification", [:reference, :name, :description]
stacked [:quantity_initial, :quantity_entries, :quantity_exits, :quantity_at_hand]
end
group "Dimensions", [:height, :width, :length]
end
show_layout :product do
inline [:reference, :name, :description]
end
end
endUsing Section Layouts
Divide the form or show layout into distinct tabs using sections. Each section represents a tab where only its fields are visible when selected:
defmodule ProductViews do
alias MyApp.Inventory
alias MyApp.Inventory.Product
auix_resource_metadata(:product, context: Inventory, schema: Product)
auix_create_ui do
edit_layout :product do
sections do
section "Details", [:reference, :name, :description]
section "Prices", [:msrp, :rrp, :list_price]
section "Images", [:image, :thumbnail]
end
end
end
endOverriding Field Options
Customize UI characteristics for specific fields by supplying keyword options:
defmodule ProductViews do
alias MyApp.Inventory
alias MyApp.Inventory.Product
auix_resource_metadata(:product, context: Inventory, schema: Product)
auix_create_ui do
index_columns :product, [:reference, name: [renderer: &upcase_text/1]]
edit_layout :product do
inline [id: [hidden: true], reference: [readonly: true, length: 30], description: [length: 255]]
end
end
endFields can be framed within a named group.
defmodule ProductViews do
alias MyApp.Inventory
alias MyApp.Inventory.Product
auix_resource_metadata(:product, context: Inventory, schema: Product)
auix_create_ui do
edit_layout :product do
group "Identification", [:reference, :name, :description]
group "Quantities", [:quantity_initial, :quantity_entries, quantity_exits, quantity_at_hand]
group "Dimensions", [:height, :width, :length]
end
end
endComplex Layouts
Layout can be more complex, by combining sections, groups, inline and field UI overrides.
defmodule ProductViews do
alias MyApp.Inventory
alias MyApp.Inventory.Product
auix_resource_metadata(:product, context: Inventory, schema: Product)
auix_create_ui do
edit_layout :product do
sections do
section "Details" do
inline do
inline [id: [hidden: true]]
group "Identification" do
inline [reference: [readonly: true]]
inline [:name, :description]
end
group "Quantities", [:quantity_initial, :quantity_entries, quantity_exits, quantity_at_hand]
end
group "Dimensions", [:height, :width, :length]
end
section "Prices", [:msrp, :rrp, :list_price]
section "Images", [:image, :thumbnail]
end
end
end
Summary
Functions
Generates a default layout_tree structure for rendering UI components based on the given layout type.
Defines a form layout for resource editing.
Defines a group sub-layout to visually segment related fields under a common title.
Registers index columns and associated options for a specific resource.
Defines an inline sub-layout that groups fields horizontally within a form or show container.
Parses a list of paths to handle sections based on the given layout type.
Defines a section within a sections container, representing a tab that contains a specific set of fields.
Defines a sections container that groups multiple section entries into tab-like structures.
Defines a read-only layout for resource display.
Defines a stacked sub-layout that groups fields vertically within a form or show container.
Functions
@spec build_default_layout_paths(list(), map(), keyword(), atom()) :: Aurora.Uix.TreePath.t()
Generates a default layout_tree structure for rendering UI components based on the given layout type.
Parameters
paths(list()): An existing list of paths. If empty, default paths are generated.resource_config(atom()): The associated resource configuration.layout_type(atom()): The rendering layout type (:index,:form, or:show).
Returns
- map(): A map representing the UI structure.
Modes and Behaviour
:indexlayout types: Generates an:indexstructure using all available fields as columns.:formand:showlayout types: Generates a:layoutstructure containing an:inlinegroup with all fields.- If paths are already provided, they are returned unchanged.
Example
iex> Aurora.Uix.Layout.Blueprint.build_default_layout_paths([], "product", %{fields: [%{field: :name}, %{field: :price}]}, [], :index) [
%{tag: :index, state: :start, opts: [], config: {:fields, [:name, :price]}},
%{tag: :index, state: :end}]
iex> build_default_layout_paths([], "product", %{fields: [%{field: :name}, %{field: :price}]}, [], :form) [
%{tag: :form, state: :start, config: {:name, "product"}, opts: []},
%{tag: :inline, state: :start, config: {:fields, [:name, :price]}, opts: []},
%{tag: :inline, state: :end},
%{tag: :form, state: :end}]
Defines a form layout for resource editing.
Parameters
name(atom()): Resource configuration name.opts(keyword(), optional): Additional layout options. See below for supported options.do_block(optional): Layout definition block.
Options
See Aurora.Uix.Layout.Options.Form for all supported options and behaviors.
:edit_title(binary() | (map() -> Phoenix.LiveView.Rendered.t())): The title for the edit form. Default:"Edit {name}", where{name}is the capitalized schema name.:edit_subtitle(binary() | (map() -> Phoenix.LiveView.Rendered.t())): The subtitle for the edit form. Default:"Use this form to manage <strong>{title}</strong> records in your database", where{title}is the capitalized table name.:new_title(binary() | (map() -> Phoenix.LiveView.Rendered.t())): The title for the new resource form. Default:"New {name}", where{name}is the capitalized schema name.:new_subtitle(binary() | (map() -> Phoenix.LiveView.Rendered.t())): The subtitle for the new resource form. Default:"Creates a new <strong>{name}</strong> record in your database", where{name}is the capitalized schema name.
Actions
The following actions are available (see Aurora.Uix.Templates.Basic.Actions.Index for details and usage):
add_row_action: {name, &fun/1}: Adds a row action at the end.insert_row_action: {name, &fun/1}: Inserts a row action at a specific position.replace_row_action: {name, &fun/1}: Replaces a row action by name.remove_row_action: name: Removes a row action by name (e.g.,:default_row_edit).add_header_action: {name, &fun/1}: Adds a header action at the end.insert_header_action: {name, &fun/1}: Inserts a header action at a specific position.replace_header_action: {name, &fun/1}: Replaces a header action by name.remove_header_action: name: Removes a header action by name (e.g.,:default_new).
Behavior
- Renders an editable form layout for the resource.
- Options allow customization of form titles, subtitles, and field arrangement.
Example
edit_layout :product, edit_title: "Edit Product" do
inline [:reference, :name, :description]
end
Defines a group sub-layout to visually segment related fields under a common title.
Parameters
title(string()): The title of the group.opts(keyword()): Additional options for the group layout.block: An optionaldoblock containing nested layout definitions.
Example
group "Identification", [:reference, :name, :description]
Registers index columns and associated options for a specific resource.
Parameters
name(atom): Resource configuration name.fields(list | keyword): List of field atoms or field/option pairs to display as columns.do_block(optional): Optional block for nested layout or further customization.
Options
:pagination_disabled?(boolean()) - If true, pagination is not used for populating the index list.:page_title(binary() | (map() - Phoenix.LiveView.Rendered.t())): The page title for the index layout. Example:page_title: "Products List"orpage_title: &custom_page_title/1.:page_subtitle(binary() | (map() - Phoenix.LiveView.Rendered.t())): The page subtitle for the index layout. Example:page_subtitle: "All available products"orpage_subtitle: &custom_page_subtitle/1.:order_by(atom() | list() | keyword()) - Order used for displaying the index. Takes precedence over any order_by set inauix_resource_metadata. SeeAurora.Uix.Layout.ResourceMetadata.auix_resource_metadata/3for details.:where(keyword()) - Where clauses to use for filtering the items to show.- Field-level options can be provided as keyword lists for each field (e.g.,
[name: [renderer: &custom_renderer/1]]).
Field-level Options
Besides the metadata options, there are some field types that can accept specific options for changing the way they are rendered.
Fields representing one-to-many association.
:order_by(atom() | list() | keyword()) -Order byused for displaying the related items. Uses the same criteria as theorder_byoption described above.:where(list()) - Allows filtering the rendered options.
Fields representing many-to-one association related field.
Those are the fields that referred the id that associates the many to one relation. For example: product_id. They are, by default, represented as a select html type.
:option_label(atom() | function()) - The label to be shown for each option. Can be:- atom() - Renders the field contents.
- function/1 - Receives the entity as an argument, must return a
Phoenix.LiveView.Rendered.t() - function/2 - Receives assigns and the entity as arguments, expected to return
Phoenix.LiveView.Rendered.t()
Actions
The following actions are available (see Aurora.Uix.Templates.Basic.Actions.Index for details and usage):
add_row_action: {name, &fun/1}: Adds a row action at the end.insert_row_action: {name, &fun/1}: Inserts a row action at a specific position.replace_row_action: {name, &fun/1}: Replaces a row action by name.remove_row_action: name: Removes a row action by name (e.g.,:default_row_edit).add_header_action: {name, &fun/1}: Adds a header action at the end.insert_header_action: {name, &fun/1}: Inserts a header action at a specific position.replace_header_action: {name, &fun/1}: Replaces a header action by name.remove_header_action: name: Removes a header action by name (e.g.,:default_new).
Note: Row-related actions (such as
add_row_action,insert_row_action,replace_row_action,remove_row_action) will receive an@auix.row_infoassign containing a tuple{id, row_entity}for the current row.
Behavior
- Fields listed in
fieldswill be rendered as columns in the index table. - Options and actions allow customization of the index page title, subtitle, and available actions.
Examples
# Basic usage with default actions and titles
index_columns :product, [:name, :price]
# Custom page title and subtitle
index_columns :product, [:name, :price],
page_title: "Products List",
page_subtitle: "All available products"
# Add a custom row action and remove the default delete action
defmodule MyApp.Actions do
def custom_action(assigns) do
~H"<.link navigate={~p"/edit_page"}"
end
end
index_columns :product, [:name, :price],
add_row_action: {:custom, &MyApp.Actions.custom_action/1},
remove_row_action: :default_row_delete
Defines an inline sub-layout that groups fields horizontally within a form or show container.
This macro accepts a list of fields (or UI override options) and an optional do block for defining nested layouts.
It is used to arrange fields side-by-side, either as a standalone block or as part of a larger layout.
Parameters
fields(list()): A list of field identifiers or keyword options for field-specific UI customizations.block: An optionaldoblock containing nested layout definitions.
Examples
Inline without a nested block:
inline [:reference, :name, :description]Inline with nested sub-layouts:
inline do
group "Basic Info" do
inline [:reference, :name]
stacked [:description, :notes]
end
end
@spec parse_sections(Aurora.Uix.TreePath.t(), atom()) :: Aurora.Uix.TreePath.t()
Parses a list of paths to handle sections based on the given layout type.
Parameters
paths(list()): A list of layout_tree maps representing the layout structure.layout_type(atom()): The layout type of parsing, such as:indexor other modes.
Returns
list(): A list of parsed paths with sections processed according to the layout type.
Examples
iex> paths = [
%{tag: :sections, state: :start},
%{tag: :section, state: :start, config: [tab_id: "tab1", label: "Tab 1"], opts: []},
%{tag: :section, state: :end},
%{tag: :sections, state: :end}
]iex> parse_sections(paths, :form) [
%{
tag: :sections,
state: :start,
config: [%{active: true, label: "Tab 1", tab_id: "tab1"}]
},
%{
tag: :section,
state: :start,
config: [active: true, tab_id: "tab1", label: "Tab 1"],
opts: []
},
%{tag: :section, state: :end},
%{tag: :sections, state: :end}]
Defines a section within a sections container, representing a tab that contains a specific set of fields.
Parameters
label(string()): The label for the section.opts(keyword()): Additional options for the section layout.block: An optionaldoblock for nested layout definitions.
Example
section "Details", [:reference, :name, :description]
Defines a sections container that groups multiple section entries into tab-like structures.
Parameters
opts(keyword()): Additional options for configuring the sections container.block: Adoblock containing one or moresectiondefinitions.
Example
sections do
section "Details", [:reference, :name]
section "Prices", [:msrp, :rrp]
end
Defines a read-only layout for resource display.
Parameters
name(atom()): Resource configuration name.opts(keyword(), optional): Options for customizing the show layout. See below for supported options.do_block(optional): Layout definition block.
Options
See Aurora.Uix.Layout.Options.Page for all supported options and behaviors.
:page_title(binary() | (map() -> Phoenix.LiveView.Rendered.t())): The page title for the show layout. Default:"{name}".:page_subtitle(binary() | (map() -> Phoenix.LiveView.Rendered.t())): The page subtitle for the show layout. Default:"Details".
Actions
The following actions are available (see Aurora.Uix.Templates.Basic.Actions.Index for details and usage):
add_row_action: {name, &fun/1}: Adds a row action at the end.insert_row_action: {name, &fun/1}: Inserts a row action at a specific position.replace_row_action: {name, &fun/1}: Replaces a row action by name.remove_row_action: name: Removes a row action by name (e.g.,:default_row_edit).add_header_action: {name, &fun/1}: Adds a header action at the end.insert_header_action: {name, &fun/1}: Inserts a header action at a specific position.replace_header_action: {name, &fun/1}: Replaces a header action by name.remove_header_action: name: Removes a header action by name (e.g.,:default_new).
Behavior
- Renders fields in a disabled/read-only state.
- All options are processed only for the
:showtag.
Examples
show_layout :product, page_title: "Product Details" do
inline [:reference, :name, :description]
end
def page_title(assigns), do: ~H"Details for {@auix.name}"
show_layout :product, page_title: &page_title/1,
page_subtitle: "Extra Info" do
inline [:reference, :name, :description]
end
Defines a stacked sub-layout that groups fields vertically within a form or show container.
This macro accepts a list of fields (or UI override options) and an optional do block for further nesting.
It is typically used to arrange fields one below the other, creating a vertical grouping that aids in visual organization.
Parameters
fields(list()): A list of field identifiers or keyword options for UI customizations.block: An optionaldoblock containing nested layout definitions.
Example
stacked [:quantity_initial, :quantity_entries, :quantity_exits, :quantity_at_hand]