{# Form chrome — HTMX form submission, Alpine dzWizard for multi-step #} {# Contract: ~/.claude/skills/ux-architect/components/form-chrome.md (UX-016) #} {% from 'macros/form_field.html' import render_field %} {% from 'macros/form_companion.html' import render_companion %} {% if form %} {# #902: dzWizard scope must wrap BOTH the stepper AND the form so the stepper's `isActive(N)` / `isCurrent(N)` / `step > N` bindings find the methods + reactive state. Previously the scope was on the `
` element — but the stepper sits ABOVE the form so it was outside scope, throwing 20+ ReferenceErrors per render. Moving the scope to the outer wrapper keeps validateStage's `$el.querySelectorAll("[data-dz-stage]")` working since stages stay inside the wrapper. v0.62 CSS refactor: inline Tailwind → semantic .dz-form-* + .dz-button primitives (components/fragments.css + components/button.css). #} {# v0.61.88 (#918): `form.layout` ("wizard"|"single_page") controls whether sections render as a multi-step wizard (existing behaviour) or stack top-to-bottom on one page. The dzWizard Alpine scope is only attached in wizard mode; single_page renders without any step state, all sections visible, single submit at the end. #} {% set is_single_page = form.sections and form.layout == "single_page" %} {% set is_wizard = form.sections and form.layout != "single_page" %}
{# Header #} {% block form_header %}

{{ form.title }}

{% endblock form_header %} {# Stepper indicator — wizard layout only #} {% if is_wizard %} {% include 'fragments/form_stepper.html' %} {% endif %} {# Form. dzWizard scope lives on the outer wrapper (above) when in wizard mode so the stepper sees it too — the form element stays scope-free here. #} {# Form errors area (swapped by HTMX on validation failure) #}
{% include 'fragments/form_errors.html' %}
{# v0.61.102 (#923): companions slot at top, after each named section anchor, and at bottom. Empty list = no companions. #} {% if form.companions %} {% for companion in form.companions if companion.position == "top" %} {{ render_companion(companion) }} {% endfor %} {% endif %} {# Fields — sectioned (wizard or single_page) or flat (delegated to UX-017 form-field). single_page renders all sections stacked without the dz-stage/x-show wrappers. #} {% block form_fields %} {% if is_wizard %} {% for section in form.sections %}

{{ section.title }}

{% if section.note %}

{{ section.note }}

{% endif %} {% for field in section.fields %} {{ render_field(field, form.initial_values) }} {% endfor %} {% if form.companions %} {% for companion in form.companions if companion.position == "below_section" and companion.section_anchor == section.name %} {{ render_companion(companion) }} {% endfor %} {% endif %}
{% endfor %} {% elif is_single_page %} {% for section in form.sections %}

{{ section.title }}

{% if section.note %}

{{ section.note }}

{% endif %} {% for field in section.fields %} {{ render_field(field, form.initial_values) }} {% endfor %} {% if form.companions %} {% for companion in form.companions if companion.position == "below_section" and companion.section_anchor == section.name %} {{ render_companion(companion) }} {% endfor %} {% endif %}
{% endfor %} {% else %} {% for field in form.fields %} {{ render_field(field, form.initial_values) }} {% endfor %} {% endif %} {% endblock form_fields %} {% if form.companions %} {% for companion in form.companions if companion.position == "bottom" %} {{ render_companion(companion) }} {% endfor %} {% endif %} {# Actions — wizard nav, single_page single submit, or standard. #} {% block form_actions %} {% if is_wizard %}
Cancel
{% else %}
Cancel
{% endif %} {% endblock form_actions %}
{% endif %}