defmodule Corex.Toast do
@moduledoc """
Phoenix implementation of [Zag.js Toast](https://zagjs.com/components/react/toast).
## Examples
```heex
<.toast_group />
```
## API Control
***Client-side***
```heex
```
***Server-side***
```elixir
def handle_event("create_info_toast", _, socket) do
{:noreply, Corex.Toast.push_toast(socket, "This is an info toast", "This is an info toast description", :info)}
end
```
"""
@doc type: :component
use Phoenix.Component
@doc """
Renders a toast group (toaster) that manages multiple toast notifications.
This component should be rendered once in your layout.
## Examples
```heex
<.toast_group />
```
## API Control
***Client-side***
```heex
```
***Server-side***
```elixir
def handle_event("create_info_toast", _, socket) do
{:noreply, Corex.Toast.push_toast(socket, "This is an info toast", "This is an info toast description", :info)}
end
```
"""
attr(:id, :string, default: nil)
attr(:placement, :string,
default: "bottom-end",
values: ~w(top-start top top-end bottom-start bottom bottom-end)
)
attr(:overlap, :boolean, default: false)
attr(:max, :integer, default: 5)
attr(:gap, :integer, default: nil)
attr(:offset, :string, default: nil)
attr(:pause_on_page_idle, :boolean, default: false)
def toast_group(assigns) do
~H"""
"""
end
@doc type: :api
@doc """
Creates a toast notification programmatically (client-side).
This function returns a JS command that can be used in event handlers.
## Examples
def handle_event("save", _params, socket) do
# ... save logic ...
{:noreply, push_event(socket, "toast-create", %{
title: "Saved!",
description: "Your changes have been saved.",
type: "success"
})}
end
Or use the JS command version:
"""
def create_toast(title, description \\ nil, type \\ :info, opts \\ []) do
duration = Keyword.get(opts, :duration, 5000)
duration_str = if duration == :infinity, do: "Infinity", else: duration
type_str =
case type do
:info -> "info"
:success -> "success"
:error -> "error"
:warning -> "warning"
:loading -> "loading"
_ -> "info"
end
Phoenix.LiveView.JS.dispatch("toast:create",
to: ".toast-group-js",
detail: %{
title: title,
description: description,
type: type_str,
duration: duration_str
}
)
end
@doc type: :api
@doc """
Server-side function to push a toast event to the client.
Use this in your LiveView event handlers.
## Examples
def handle_event("save", _params, socket) do
# ... save logic ...
{:noreply, push_toast(socket, "Saved!", "Your changes have been saved.", :success)}
end
"""
def push_toast(socket, title, description \\ nil, type \\ :info, duration \\ 5000) do
type_str =
case type do
:info -> "info"
:success -> "success"
:error -> "error"
:warning -> "warning"
:loading -> "loading"
_ -> "info"
end
Phoenix.LiveView.push_event(socket, "toast-create", %{
title: title,
description: description,
type: type_str,
duration: duration
})
end
end