{#- chirp-ui: Toast component htmx OOB toast notifications with stacking, swipe-dismiss, and server-driven loading→success/error updates (sonner-grade feedback). Usage: from "chirpui/toast.html" import toast, toast_container, toast_pending, toast_resolve Place the container once in your base template: toast_container() Return a toast from any htmx response (OOB swap): toast("Item saved successfully!", variant="success") toast("Something went wrong.", variant="error", dismissible=true) Server-driven status flow (HTMX-native promise pattern): # 1) POST handler returns pending toast with stable id toast_pending("Saving…", id="save-item-42") # 2) follow-up response replaces the same toast by id toast_resolve("Saved!", id="save-item-42", variant="success") toast_resolve("Save failed.", id="save-item-42", variant="error") -#} {% def toast_container(id="chirpui-toasts", cls="", limit=5) %}
{% end %} {% def _toast_inner(message, variant, id=none, dismissible=true, cls="", duration=none, oob_swap=none) %} {% set variant = variant | validate_variant(("info","success","warning","error","danger","loading"), "info") %} {% set _duration = duration if duration is not none else "" %} {% end %} {% def toast(message, variant="info", id=none, dismissible=true, oob=true, replace=false, container_id="chirpui-toasts", cls="", duration=none) %} {% if replace and id %} {{ _toast_inner(message, variant, id=id, dismissible=dismissible, cls=cls, duration=duration, oob_swap="true") }} {% elif oob %}
{{ _toast_inner(message, variant, id=id, dismissible=dismissible, cls=cls, duration=duration) }}
{% else %} {{ _toast_inner(message, variant, id=id, dismissible=dismissible, cls=cls, duration=duration) }} {% end %} {% end %} {% def toast_pending(message, id, dismissible=false, container_id="chirpui-toasts", cls="") %} {{ toast(message, variant="loading", id=id, dismissible=dismissible, container_id=container_id, cls=cls) }} {% end %} {% def toast_resolve(message, id, variant="success", dismissible=true, duration=5000, cls="") %} {{ toast(message, variant=variant, id=id, dismissible=dismissible, replace=true, duration=duration, cls=cls) }} {% end %}