{% load i18n brickwork_icons brickwork_components %} {% comment %} Full-width banner alert (STA-008/009). role="alert" so it is announced. The status icon is decorative (the variant + text carry the meaning; the icon is reinforcement, not the sole signal). This is the loud surface for page-level errors and status, distinct from a field's inline error (forms/_field.html). variant ("info" | "success" | "warning" | "danger", default "info"): the tag path validates via TemplateSyntaxError; the include path emits the whole class attribute through {% bw_attr ... allow= prefix= %} (ADR-097). An absent value defaults to "info"; an unrecognised include-path value omits class entirely (no silent fallback modifier). Dismissible (04-interfaces 4b Dismissible section, 0.9.0, CMP-010): with the tag's dismissible=True the root gains x-data="bwDismissible()" (semver-public, BR-BW-JS-004; no props, state { visible }, method dismiss(), emits bw:dismiss { id }) and an icon-only close button ships WITH the hidden attribute; bwDismissible removes hidden at init, so the no-JS floor shows no dead control. Dismissal removes the element from the DOM only; persistence stays host-owned (CMP-012). Exit at --bw-duration-fast/--bw-ease-in (MOT-007's clear-quickly tier); reduced motion removes instantly (BR-BW-TOK-009). REGRESSION NOTE: with dismissible=False (the default) the rendered output is byte-identical to the 0.8.0 template; the conditional blocks below are laid out so the False path adds not even whitespace. DIRECT INCLUDE (2.0.0): {% bw_alert %} derives `icon` from `variant` before rendering, but a plain {% include %} with only variant/title/message (the copy-paste example shape this package now documents, ADR-056) supplies no `icon` at all, and passing that undefined value to {% bw_icon %} raised IconNotFoundError for the empty name. The variant-to-icon mapping is therefore resolved HERE as a fallback, so both call shapes work. The tag path is unaffected: it still passes an explicit `icon`, which {% firstof %} takes ahead of the fallback, so its output is byte-identical to 1.x. The chain sits at the template's top level on purpose: an `{% ... as %}` assignment made inside an `{% if %}` body would fall out of scope before the icon line. Named blocks (semver-public, BR-BW-TPL-001): body: Empty by default; a filled block adds extra content under the title/message lines. Prefixed alert_body 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 the removed alert_body name produces nothing for that fill. body stays markup-only by design (icvoss/django-brickwork#398 sweep): its role is "extra content" laid out under the existing title/message lines (themselves already plain context variables), not a replacement for either, so there is no single body= string it stands in for. Passing a body= context variable is therefore still silently discarded, correctly. States: dismissed/not-dismissed when dismissible=True (x-data="bwDismissible()", state { visible }); the no-JS floor renders the close button with the hidden attribute, removed at Alpine init, so a JS-disabled page shows no dead control. Four variant states (info/success/warning/danger, default info), each pairing a fixed icon with its own tint and border colour. Accessibility: role="alert" so the whole banner is announced on render; the status icon is decorative (bw_icon decorative=True), the variant colour and text carry the meaning, never the icon alone. The dismiss control is an icon-only button with an aria-label (translated "Dismiss"). Covered by axe.spec.mjs indirectly via app/confirm.html and app/detail.html (both compose it) and via sections-*.html (content/callout.html); the dismiss markup and its bwDismissible() wiring are asserted at the Python/string level (tests/test_components.py, tests/test_integration.py), not by a browser-driven dismiss interaction in the a11y suites. Responsive: no breakpoint switch; no width-dependent CSS on any .bw-alert* selector. The banner is full-width within its container at every viewport size. {% endcomment %} {% firstof variant "info" as bw_alert_variant %}{% if bw_alert_variant == "success" %}{% firstof icon "success" as bw_alert_icon %}{% elif bw_alert_variant == "warning" %}{% firstof icon "alert-triangle" as bw_alert_icon %}{% elif bw_alert_variant == "danger" %}{% firstof icon "alert-circle" as bw_alert_icon %}{% else %}{% firstof icon "info" as bw_alert_icon %}{% endif %}
{% bw_icon bw_alert_icon size="md" decorative=True css_class="bw-alert__icon" %}
{% if title %}

{{ title }}

{% endif %} {% if message %}

{{ message }}

{% endif %} {% block body %}{% endblock %}
{% if dismissible %}{% translate "Dismiss" as bw_alert_close_label %} {% endif %}