A pile of toasts that opens into a list when you point at it: notices pushed from the server that never cover
the screen. Put one toast_group/1 in the layout and push toasts to it from any LiveView with put_toast/4,
update_toast/3, dismiss_toast/2 and clear_toasts/1.
A new toast enters from below and pushes the others behind the pile. Closed, only the front one shows and up
to two peek behind it, smaller and without text. With the pointer over it, or the focus inside, the pile opens
into a list with a 12px gap that does not close it. The timers pause while it is open and while the tab is
hidden, and go on from where they stopped. Alt+T moves the focus to the pile, Esc closes the focused toast
and a drag sideways (past 80px) dismisses it. A :risk toast is announced at once (role="alert"), the rest
politely (role="status") inside a region with aria-live="polite". A :loading toast never leaves by
itself: update_toast/3 turns it into :ok or :risk with the same id.
Variants: :default, :ok, :warn, :risk, :info, :ai and :loading (a spinning icon). An action is
action: %{label: "Undo", event: "undo", value: %{id: 9}}: the button sends event with value back to the
LiveView (or to target) and closes the toast.
The library has no language: every text (title, description, action label) comes from the caller, and the
close button takes its name from dismiss_label. The icons are drawn here as defaults and replaced by the
:icon slot (it receives the variant) and the :close_icon slot. The list itself belongs to the browser
(phx-update="ignore"), so a re-render never disturbs a pile that is open. From the page, without the server:
window.dispatchEvent(new CustomEvent("dui:toast", {detail: {title: "Copied"}})).
<DevactionUI.ToastGroup.toast_group flash={@flash} label="Notifications (Alt+T)" dismiss_label="Close" />
socket |> put_toast(:ok, "Review published", description: "PR #214")
socket |> put_toast(:loading, "Building report", id: "report")
socket |> update_toast("report", variant: :ok, title: "Report ready")
Summary
Functions
Closes every toast, :loading ones included. opts: :group, see put_toast/4.
Closes the toast with id. opts: :group, see put_toast/4.
Pushes a toast to the group of the page. opts: :id (to update or dismiss it later), :description,
:duration (milliseconds, 0 keeps it until it is closed; :loading ignores it), :action
(%{label: "Undo", event: "undo", value: %{id: 9}}) and :group.
The group of toasts: one per layout, filled by put_toast/4 and its siblings.
Changes the toast with id in place: any of :variant, :title, :description, :duration and :action
(and :group, see put_toast/4). Changing the variant or the duration restarts its timer, so a :loading
toast turned :ok closes after the group's duration.
Types
Functions
@spec clear_toasts(Phoenix.LiveView.Socket.t(), keyword()) :: Phoenix.LiveView.Socket.t()
Closes every toast, :loading ones included. opts: :group, see put_toast/4.
@spec dismiss_toast(Phoenix.LiveView.Socket.t(), String.t(), keyword()) :: Phoenix.LiveView.Socket.t()
Closes the toast with id. opts: :group, see put_toast/4.
@spec put_toast(Phoenix.LiveView.Socket.t(), variant(), String.t(), keyword()) :: Phoenix.LiveView.Socket.t()
Pushes a toast to the group of the page. opts: :id (to update or dismiss it later), :description,
:duration (milliseconds, 0 keeps it until it is closed; :loading ignores it), :action
(%{label: "Undo", event: "undo", value: %{id: 9}}) and :group.
LiveView delivers server events to every hook of the page, so a page with more than one group names the
one it means with group: "id-of-the-group"; without it every group shows the toast.
@spec toast_group(map()) :: Phoenix.LiveView.Rendered.t()
The group of toasts: one per layout, filled by put_toast/4 and its siblings.
Attributes
id(:string) - Defaults to"toasts".flash(:map) - the flash of the socket:infoshows as an:oktoast anderroras a:riskone. Defaults to%{}.position(:string) - Defaults to"bottom-right". Must be one of"bottom-right","bottom-left","bottom-center","top-right","top-left", or"top-center".visible(:integer) - how many show in the closed pile: the front one and the ones peeking behind it. Defaults to3.duration(:integer) - milliseconds before a toast closes by itself;0keeps them until they are closed. Defaults to4000.label(:string) (required) - the region's name for assistive technology, such asNotifications (Alt+T).dismiss_label(:string) (required) - the name of the close button of each toast.target(:any) - the@myself(or selector) that receives the events of the toast actions. Defaults tonil.inline(:boolean) - lay the group out in the flow (relative) instead of fixed to the viewport. Defaults tofalse.hotkey(:boolean) - whetherAlt+Tmoves the focus here; turn it off in all but one group when a page has several. Defaults totrue.class(:any) - Defaults tonil.- Global attributes are accepted.
Slots
icon- replaces the icon of each variant (:let={variant}::ok,:warn,:risk,:info,:ai,:loading).close_icon- replaces the × of the close button.
@spec update_toast(Phoenix.LiveView.Socket.t(), String.t(), keyword() | map()) :: Phoenix.LiveView.Socket.t()
Changes the toast with id in place: any of :variant, :title, :description, :duration and :action
(and :group, see put_toast/4). Changing the variant or the duration restarts its timer, so a :loading
toast turned :ok closes after the group's duration.