{% with messages = get_flashed_messages(with_categories=true) %} {% if messages %} {# aria-live on the always-present wrapper, not role="alert" per message, so messages that land in it via a fragment swap are announced. `assertive` only for errors — a success confirmation should not interrupt the reader. #}
{% for category, message in messages %} {% set alert_type = 'info' %} {% set alert_icon = 'notifications' %} {% if category == 'error' or category == 'danger' %} {% set alert_type = 'danger' %}{% set alert_icon = 'cancel' %} {% elif category == 'warning' %} {% set alert_type = 'warning' %}{% set alert_icon = 'notifications' %} {% elif category == 'success' %} {% set alert_type = 'success' %}{% set alert_icon = 'check' %} {% endif %}
{# The icon plus its visually-hidden name carries the category, so it does not rely on colour. #} {{ icon(alert_icon, label=construct.t("alert-" ~ alert_type)) }} {{ t(message) }} {# Dismissal is the reader's choice; nothing removes a message before it has been read. #}
{% endfor %}
{% endif %} {% endwith %}