{% load i18n brickwork_icons brickwork_components %} {% comment %} Modal dialog (04-interfaces section 4b). Consumed by EXTENDING, like patterns/: a consumer's modal partial opens with {% extends "brickwork/components/_modal.html" %} and fills the named blocks. DUAL CONSUMPTION, one partial, two documented render paths (BR-BW-HTMX-001): 1. htmx path (needs the #bw-modal-root container shell/base.html ships from 0.9.0): the trigger is a real anchor carrying hx-get hx-target="#bw-modal-root" hx-swap="innerHTML"; the view returns the consumer's modal partial and on insertion bwModal opens it as an overlay. 2. no-JS floor: the SAME anchor's href is a full-page route; the view (branching on request.htmx) renders the SAME consumer partial inside a full page (typically a page extending shell/centred.html whose content block {% include %}s the consumer's modal partial). With no JavaScript this markup is simply an in-flow, visible panel on that page: the modal is then a page, which is the floor. Nothing here is display:none at rest; the scrim and fixed overlay positioning apply only under the JS-set bw-modal--open state, so the floor never hides content behind JavaScript. Named blocks (semver-public, BR-BW-TPL-001): title: Defaults to rendering {{ title }} inside the chrome-owned heading (heading-sm type role). Prefixed modal_title was removed in 4.0.0. body: The dialog content. A form inside it follows BR-BW-HTMX-003 unchanged (hx-target="this" hx-swap="outerHTML", 422 re-render with inline errors); a failed request NEVER closes the modal (CBH-026). On success the view closes it server-side: respond 204 (or with OOB toast content) plus HX-Trigger: {"bw:modal:close": {"id": ""}}; bwModal listens for bw:modal:close at the window. Prefixed modal_body was removed in 4.0.0. footer: Empty renders nothing; the filler owns the wrapper element (write ), matching _card.html's region convention. Sticky header/footer with a scrolling body per CMP-021. Prefixed modal_footer was removed in 4.0.0. A block name this file does not define is SILENTLY DISCARDED by Django: no error, no warning, DEBUG=True does not catch it. Filling a removed prefixed name (modal_title, modal_body, modal_footer) produces a structurally valid, empty region for that fill. body and footer stay markup-only by design (icvoss/django-brickwork#398 sweep): body is "the dialog content", commonly a form wired to BR-BW-HTMX-003, and footer's filler owns its own