{% extends "brickwork/shell/app.html" %} {% comment %} A create/edit page: one form on a page. COPY THIS FILE into your project and edit it. It is not on the template loader path, so you cannot extend it (ADR-056). What your view must supply: form your own Django form (bound on POST) nav_items / nav_active as in list.html THE ONE RULE HERE: you own the
element, brickwork never emits it. That is not a limitation, it is the only sound arrangement: only your project knows its own action URL, and a template that wrapped your fields in its own would put your submit button outside it. So the , the csrf_token, and the submit all live together in this file, which you own. States: valid/invalid per field (bw_form renders the bound form's own errors inline); the 422 HTMX re-render path documented above swaps this same region with inline errors, never a full page reload, when wired. Accessibility: inherits shell/app.html's skip link, sidebar/drawer nav and page-header region; every field renders through the standard forms/_field.html chrome (label/aria-describedby/error wiring); the cancel link is a real anchor, never a button pretending to navigate. Covered by the archetype harness's full gate sweep (render, axe WCAG 2.2 AA, no horizontal overflow, light/dark distinctness, skip-link first-tab-stop with JS disabled) at every W0.1 breakpoint, both themes; the underlying bw_form grid layout and its error states are additionally covered by axe.spec.mjs against form-*.html/form-errors-*.html. Responsive: no breakpoint switch of its own; inherits shell/app.html's sidebar-to-drawer collapse at --bw-breakpoint-md (48rem). bw_form's own grid layout (when grid_columns is set) collapses to one column below --bw-breakpoint-sm (40rem), per that tag's own documentation. {% endcomment %} {% load brickwork_components brickwork_forms brickwork_nav %} {% block page_title %}New invoice - Northwind{% endblock %} {% block sidebar %}{% bw_nav nav_items nav_active %}{% endblock %} {% block sidebar_mobile %}{% bw_nav nav_items nav_active %}{% endblock %} {% block brand_wordmark %}Northwind{% endblock %} {% block page_header %} {% include "brickwork/components/_page_header.html" with title="New invoice" description="Raise an invoice against one of your accounts." %} {% endblock %} {% block content %}
{% comment %} Point the action at your own URL. {{ request.path }} posts back to this same page, which is the usual shape for a create/edit view: on success the view redirects, on failure it re-renders this page with the bound, invalid form and the errors appear inline automatically. bw_form renders form.visible_fields() generically, so it works with any form: ModelForm, plain Form, allauth's, your own. It also includes the non-field error region itself, so never include _form_errors.html a second time beside it. No JS is needed for any of this. If you add htmx, a validation failure should return 422 with this same page re-rendered; htmx 2 needs the 422 status opted in to swap (see INTEGRATION.md), which is the one line people miss. {% endcomment %} {% csrf_token %} {% bw_form form %} {% comment %} The submit sits INSIDE the form, beside the fields. A cancel link beside it is an ordinary anchor, not a button: it navigates, it does not submit. {% endcomment %}
{% bw_button "Save invoice" type="submit" variant="primary" %} {% bw_button "Cancel" variant="ghost" href="/invoices/" %}
{% endblock %}