Form groups and layout DSL
v0.0.1
The groups and layout sections of a resource's form block arrange fields into groups, groups into steps, and add a header, a footer and notices. The hierarchy is step, then groups, then fields.
groups.group
Declares a named group of fields. A field may sit in at most one group. It sits at mishka_gervaz.form.groups.group.
Call: group name
Arguments:
| Argument | Type | Default | Description |
|---|---|---|---|
name | atom | none | Required. Group identifier. |
Options:
| Option | Type | Default | Description |
|---|---|---|---|
fields | list(atom) | none | Required. Names of the fields in the group. A field may sit in at most one group. |
collapsed | boolean | false | Start collapsed. The value is compiled into the config, but no built-in template or handler reads it. |
collapsible | boolean | false | Can be collapsed by user. |
position | any | none | Group position (integer, :first, :last). The value is compiled into the config, but no built-in template or handler reads it. |
visible | boolean | (any -> any) | true | Static or dynamic visibility. fn state -> boolean() end. |
restricted | boolean | (any -> any) | false | Restrict to master users. true or fn state -> boolean() end. |
group ui
How the group is drawn. It sits at mishka_gervaz.form.groups.group.ui.
| Option | Type | Default | Description |
|---|---|---|---|
label | String.t | (-> any) | none | Group label. |
icon | String.t | none | Group icon. The value is compiled into the config, but no built-in template or handler reads it. |
description | String.t | none | Group description. The value is compiled into the config, but no built-in template or handler reads it. |
class | String.t | none | Group CSS classes. |
header_class | String.t | none | Group header CSS classes. The value is compiled into the config, but no built-in template or handler reads it. |
columns | 1 | 2 | 3 | 4 | none | Number of grid columns for this group (overrides global layout columns). |
extra | map | %{} | Additional options. The value is compiled into the config, but no built-in template or handler reads it. |
layout
Picks the layout mode and the grid. Its entities are the steps and the chrome. It sits at mishka_gervaz.form.layout.
| Option | Type | Default | Description |
|---|---|---|---|
columns | 1 | 2 | 3 | 4 | 1 | Number of grid columns (1-4). Only 1 to 4 change the grid. Any other value gives one column. |
mode | :standard | :wizard | :tabs | :standard | :standard draws one page. :wizard shows one step at a time. :tabs needs steps too, and the Standard template draws it one step at a time as well. Free jumping needs navigation :free and a goto_step event, which no built-in element sends. :wizard and :tabs need steps, and :standard forbids them. |
navigation | :sequential | :free | :sequential | :sequential enforces the order of the steps. :free lets the reader jump, and is invalid with :wizard. |
persistence | :none | :ets | :client_token | :none | Where step data is meant to live between steps: :none, :ets or :client_token. The value is compiled into the config, but no built-in template or handler reads it. It is readable with Info.Form.persistence/1. |
responsive | boolean | true | Enable responsive layout adjustments. The value is compiled into the config, but no built-in template or handler reads it. |
step
Declares a step of a wizard or a tabs form. It sits at mishka_gervaz.form.layout.step.
Call: step name
Arguments:
| Argument | Type | Default | Description |
|---|---|---|---|
name | atom | none | Required. Step identifier. |
Options:
| Option | Type | Default | Description |
|---|---|---|---|
groups | list(atom) | none | Required. Names of the groups in the step. A group may sit in at most one step. |
action | atom | none | Validation action to run when leaving this step. Gervaz does not call it. Navigation goes through the step handler's can_advance?/2. |
summary | boolean | false | Marks the step as the review step. At most one step may set it. Gervaz checks when it compiles that only one step sets it. The built-in template does not draw a step differently for it. |
on_enter | (any -> any) | none | Callback invoked when entering the step. Receives state, returns state. Gervaz does not call it. Navigation goes through the step handler's can_advance?/2. |
before_leave | (any -> any) | none | Callback invoked before leaving the step. Return {:halt, state} to block navigation. Gervaz does not call it. Navigation goes through the step handler's can_advance?/2. |
after_leave | (any -> any) | none | Callback invoked after leaving the step. Receives state, returns state. Gervaz does not call it. Navigation goes through the step handler's can_advance?/2. |
visible | boolean | (any -> any) | true | Static or dynamic visibility. fn state -> boolean() end. The value is compiled into the config, but no built-in template or handler reads it. |
step ui
How the step is drawn. It sits at mishka_gervaz.form.layout.step.ui.
| Option | Type | Default | Description |
|---|---|---|---|
label | String.t | (-> any) | none | Step label. |
icon | String.t | none | Step icon. The value is compiled into the config, but no built-in template or handler reads it. |
description | String.t | none | Step description. The value is compiled into the config, but no built-in template or handler reads it. |
class | String.t | none | Step CSS classes. The value is compiled into the config, but no built-in template or handler reads it. |
header_class | String.t | none | Step header CSS classes. The value is compiled into the config, but no built-in template or handler reads it. |
extra | map | %{} | Additional options. |
header
A title and description drawn above the fields. It sits at mishka_gervaz.form.layout.header.
| Option | Type | Default | Description |
|---|---|---|---|
title | String.t | (-> any) | (any -> any) | none | Header title. String, fn -> _ end, or fn state -> _ end. |
description | String.t | (-> any) | (any -> any) | none | Header description. String, fn -> _ end, or fn state -> _ end. |
icon | String.t | none | Heroicon name (e.g., "hero-shield-check"). |
class | String.t | none | CSS classes for the header wrapper. |
render | (any -> any) | (any, any -> any) | none | Custom HEEx render. fn assigns -> ~H"..." end or fn assigns, state -> ~H"..." end. |
extra | map | %{} | Additional template-specific options. The value is compiled into the config, but no built-in template or handler reads it. |
visible | boolean | (any -> any) | true | Static or dynamic visibility. fn state -> boolean() end. |
restricted | boolean | (any -> any) | false | Restrict to master users. true or fn state -> boolean() end. |
footer
Static content drawn below the submit row. It sits at mishka_gervaz.form.layout.footer.
| Option | Type | Default | Description |
|---|---|---|---|
content | String.t | (-> any) | (any -> any) | none | Footer content. String, fn -> _ end, or fn state -> _ end. |
class | String.t | none | CSS classes for the footer wrapper. |
render | (any -> any) | (any, any -> any) | none | Custom HEEx render. fn assigns -> ~H"..." end or fn assigns, state -> ~H"..." end. |
extra | map | %{} | Additional template-specific options. The value is compiled into the config, but no built-in template or handler reads it. |
visible | boolean | (any -> any) | true | Static or dynamic visibility. fn state -> boolean() end. |
restricted | boolean | (any -> any) | false | Restrict to master users. true or fn state -> boolean() end. |
notice
A static alert or banner with a position and an optional binding. It sits at mishka_gervaz.form.layout.notice.
Call: notice name
Arguments:
| Argument | Type | Default | Description |
|---|---|---|---|
name | atom | none | Required. Unique notice identifier (used for dismiss tracking). |
Options:
| Option | Type | Default | Description |
|---|---|---|---|
position | any | :form_top | Where the notice is drawn. Valid atoms and tuples are listed below the table. The default is :form_top. |
type | :info | :warning | :error | :success | :neutral | :info | Visual style: :info, :warning, :error, :success, or :neutral. |
title | String.t | (-> any) | (any -> any) | none | Notice title. String, fn -> _ end, or fn state -> _ end. |
content | String.t | (-> any) | (any -> any) | none | Notice body. String, fn -> _ end, or fn state -> _ end. |
icon | String.t | none | Heroicon name. |
dismissible | boolean | false | Whether the user can dismiss this notice. |
bind_to | nil | :validation | :uploads | :dirty | none | Draws the notice only while a condition holds. See the list below the table. Combined with show_when using AND. |
show_when | (any -> any) | none | Custom predicate fn state -> boolean() end. Combined with bind_to (AND). |
only_steps | list(atom) | none | Scopes the notice to these steps in wizard and tabs mode. The names must exist. |
render | (any -> any) | (any, any -> any) | none | Custom HEEx render. fn assigns -> ~H"..." end or fn assigns, state -> ~H"..." end. |
visible | boolean | (any -> any) | true | Static or dynamic visibility. fn state -> boolean() end. |
restricted | boolean | (any -> any) | false | Restrict to master users. true or fn state -> boolean() end. |
Valid position values:
| Position | Where the notice is drawn |
|---|---|
:form_top | Inside the form element, above the header. The default. |
:before_header, :after_header | Around the form header. |
:before_groups | Before the groups. |
:before_fields | Accepted, and the Standard template never draws it. Use :before_groups. |
:before_submit | Above the submit and cancel row. |
:form_bottom | Below the submit row, inside the form. |
:form_footer | Below the form footer. The last slot. |
{:before_group, name}, {:after_group, name} | Beside a declared group. |
Valid bind_to values:
| Value | The notice shows while |
|---|---|
:validation | The form has errors. |
:uploads | Any registered upload has errors. Nothing in the built-in code sets upload errors, so this notice does not show. |
:dirty | The form has unsaved changes. |
notice ui
Classes for the notice. It sits at mishka_gervaz.form.layout.notice.ui.
| Option | Type | Default | Description |
|---|---|---|---|
class | String.t | none | CSS classes for the notice wrapper. |
extra | map | %{} | Additional template-specific options. The value is compiled into the config, but no built-in template or handler reads it. |
Layout rules
- Steps are required in
:wizardand:tabsmodes and forbidden in:standardmode. - Gervaz reports
navigation :freewith:wizardwhen it compiles. Use:tabsfor free navigation. - Every group named in a step must exist, and a group may sit in at most one step.
- At most one step may set
summary true. - Notice names are unique within the form.