{% 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: present SINCE 3.4.0, the concise successor to the deprecated modal_title block below (ADR-077 SS4). Defaults to rendering {{ title }} inside the chrome-owned heading (heading-sm type role). body: present SINCE 3.4.0, the concise successor to the deprecated modal_body block below (ADR-077 SS4). 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. footer: present SINCE 3.4.0, the concise successor to the deprecated modal_footer block below (ADR-077 SS4). 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. modal_title, modal_body, modal_footer: present since before 3.4.0 (unchanged back to at least 3.2.1). DEPRECATED, removed at 4.0 (ADR-077 SS4, BR-BW-TPL-001/BR-BW-VER-001). Kept as additional empty extension points for backwards compatibility: a shipped block name cannot be renamed silently. Both a concise block and its deprecated counterpart render when both are filled; a caller migrating to the concise name fills title/body/footer only. A block name this file does not define is SILENTLY DISCARDED by Django: no error, no warning, DEBUG=True does not catch it. A consumer pinned below 3.4.0 who reads title/body/footer from a newer checkout gets a structurally valid, entirely empty modal that still passes template loading; check this header against your pinned version before relying on a name. 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