Use live_toast instead of built-in flash

Precursor for building better notifications
This commit is contained in:
Claudio Ortolina
2025-06-07 08:27:25 +01:00
parent a005a3c203
commit 0aa0a19a00
10 changed files with 19 additions and 147 deletions
+1
View File
@@ -3,6 +3,7 @@
@source "../js";
@source "../../lib/music_library_web";
@source "../../deps/fluxon/**/*.*ex";
@source "../../deps/live_toast/lib/**/*.*ex";
/* A Tailwind plugin that makes "hero-#{ICON}" classes available.
The heroicons installation itself is managed by your mix.exs */
+2
View File
@@ -24,9 +24,11 @@ import topbar from "../vendor/topbar";
import { Hooks as FluxonHooks, DOM as FluxonDOM } from "fluxon";
import BarcodeScannerHook from "./barcode-scanner";
import confetti from "canvas-confetti";
import { createLiveToastHook } from "live_toast";
let Hooks = FluxonHooks;
Hooks.BarcodeScanner = BarcodeScannerHook;
Hooks.LiveToast = createLiveToastHook();
let csrfToken = document
.querySelector("meta[name='csrf-token']")
+2 -1
View File
@@ -1,6 +1,7 @@
{
"dependencies": {
"barcode-detector": "^3.0.0",
"canvas-confetti": "^1.9.3"
"canvas-confetti": "^1.9.3",
"live_toast": "file:../deps/live_toast"
}
}
@@ -34,90 +34,6 @@ defmodule MusicLibraryWeb.CoreComponents do
defdelegate separator(assigns), to: Fluxon.Components.Separator
defdelegate sheet(assigns), to: Fluxon.Components.Sheet
@doc """
Renders flash notices.
## Examples
<.flash kind={:info} flash={@flash} />
<.flash kind={:info} phx-mounted={show("#flash")}>Welcome Back!</.flash>
"""
attr :id, :string, doc: "the optional id of flash container"
attr :flash, :map, default: %{}, doc: "the map of flash messages to display"
attr :title, :string, default: nil
attr :kind, :atom, values: [:info, :warning, :error], doc: "used for styling and flash lookup"
attr :rest, :global, doc: "the arbitrary HTML attributes to add to the flash container"
slot :inner_block, doc: "the optional inner block that renders the flash message"
def flash(assigns) do
assigns = assign_new(assigns, :id, fn -> "flash-#{assigns.kind}" end)
~H"""
<div
:if={msg = render_slot(@inner_block) || Phoenix.Flash.get(@flash, @kind)}
id={@id}
phx-click={JS.push("lv:clear-flash", value: %{key: @kind}) |> hide("##{@id}")}
role="alert"
class={[
"fixed top-2 right-2 mr-2 w-80 sm:w-96 z-50 rounded-md shadow-md p-3 ring-1 ring-zinc-400 border-l-2",
@kind == :info &&
"border-l-emerald-500 bg-white dark:bg-zinc-700 text-emerald-700 dark:text-emerald-300",
@kind == :warning &&
"border-l-yellow-500 bg-white dark:bg-zinc-700 text-yellow-900 dark:text-yellow-300",
@kind == :error &&
"border-l-red-500 bg-white dark:bg-zinc-700 text-red-900 dark:text-red-300"
]}
{@rest}
>
<p :if={@title} class="flex items-center gap-1.5 text-sm font-semibold leading-6">
<.icon :if={@kind == :info} name="hero-information-circle-mini" class="h-4 w-4" />
<.icon :if={@kind == :warning} name="hero-exclamation-circle-mini" class="h-4 w-4" />
<.icon :if={@kind == :error} name="hero-exclamation-circle-mini" class="h-4 w-4" />
{@title}
</p>
<p class="mt-2 text-sm leading-5 text-zinc-700 dark:text-zinc-300">{msg}</p>
<button type="button" class="group absolute top-1 right-1 p-2" aria-label={gettext("close")}>
<.icon
name="hero-x-mark-solid"
class="text-zinc-700 dark:text-zinc-100 h-5 w-5 opacity-40 group-hover:opacity-70"
/>
</button>
</div>
"""
end
@doc """
Shows the flash group with standard titles and content.
## Examples
<.flash_group flash={@flash} />
"""
attr :flash, :map, required: true, doc: "the map of flash messages"
attr :id, :string, default: "flash-group", doc: "the optional id of flash container"
def flash_group(assigns) do
~H"""
<div id={@id}>
<.flash kind={:info} title={gettext("Success!")} flash={@flash} />
<.flash kind={:warning} title={gettext("Warning!")} flash={@flash} />
<.flash kind={:error} title={gettext("Error!")} flash={@flash} />
<.flash
id="server-error"
kind={:error}
title={gettext("Something went wrong!")}
phx-disconnected={show(".phx-server-error #server-error")}
phx-connected={hide("#server-error")}
hidden
>
{gettext("Hang in there while we get back on track")}
<.icon name="hero-arrow-path" class="ml-1 h-3 w-3 animate-spin" />
</.flash>
</div>
"""
end
@doc """
Renders a simple form.
@@ -90,7 +90,12 @@
</nav>
<main class="px-4 py-4 max-sm:pb-20 sm:px-6 lg:px-8">
<div class="mx-auto max-w-screen-xl">
<.flash_group flash={@flash} />
<LiveToast.toast_group
flash={@flash}
corner={:top_right}
connected={assigns[:socket] != nil}
toasts_sync={assigns[:toasts_sync]}
/>
{@inner_content}
</div>
</main>
@@ -1,6 +1,11 @@
<main class="px-4 py-8 max-sm:pb-20 sm:px-6 lg:px-8">
<div class="mx-auto max-w-5xl">
<.flash_group flash={@flash} />
<LiveToast.toast_group
flash={@flash}
corner={:top_right}
connected={assigns[:socket] != nil}
toasts_sync={assigns[:toasts_sync]}
/>
{@inner_content}
</div>
</main>
+1
View File
@@ -65,6 +65,7 @@ defmodule MusicLibrary.MixProject do
depth: 1},
{:fluxon, "~> 1.1.0", repo: :fluxon},
{:flagmojis, "~> 1.0"},
{:live_toast, "~> 0.8.0"},
# Dev tooling
{:phoenix_live_reload, "~> 1.2", only: :dev},
+1
View File
@@ -29,6 +29,7 @@
"hpax": {:hex, :hpax, "1.0.3", "ed67ef51ad4df91e75cc6a1494f851850c0bd98ebc0be6e81b026e765ee535aa", [:mix], [], "hexpm", "8eab6e1cfa8d5918c2ce4ba43588e894af35dbd8e91e6e55c817bca5847df34a"},
"jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"},
"live_debugger": {:hex, :live_debugger, "0.2.4", "2e0b02874ca562ba2d8cebb9e024c25c0ae9c1f4ee499135a70814e1dea6183e", [:mix], [{:igniter, ">= 0.5.40 and < 1.0.0-0", [hex: :igniter, repo: "hexpm", optional: true]}, {:phoenix_live_view, "~> 0.20.4 or ~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}], "hexpm", "bfd0db143be54ccf2872f15bfd2209fbec1083d0b06b81b4cedeecb2fa9ac208"},
"live_toast": {:hex, :live_toast, "0.8.0", "d7e24801a9a966d8e48872767ac33c50fc14640ac5272128becfc534fabd99b7", [:mix], [{:ecto, ">= 3.11.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:gettext, ">= 0.26.2", [hex: :gettext, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:phoenix, ">= 1.7.19", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_live_view, ">= 1.0.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}], "hexpm", "7e64435131b7731698908d59f7ba9f5092df8a3720814f26edf57e99d97a803c"},
"mime": {:hex, :mime, "2.0.7", "b8d739037be7cd402aee1ba0306edfdef982687ee7e9859bee6198c1e7e2f128", [:mix], [], "hexpm", "6171188e399ee16023ffc5b76ce445eb6d9672e2e241d2df6050f3c771e80ccd"},
"mint": {:hex, :mint, "1.7.1", "113fdb2b2f3b59e47c7955971854641c61f378549d73e829e1768de90fc1abf1", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1 or ~> 0.2.0 or ~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "fceba0a4d0f24301ddee3024ae116df1c3f4bb7a563a731f45fdfeb9d39a231b"},
"nimble_options": {:hex, :nimble_options, "1.1.1", "e3a492d54d85fc3fd7c5baf411d9d2852922f66e69476317787a7b2bb000a61b", [:mix], [], "hexpm", "821b2470ca9442c4b6984882fe9bb0389371b8ddec4d45a9504f00a66f650b44"},
-30
View File
@@ -52,11 +52,6 @@ msgstr ""
msgid "Error importing record"
msgstr ""
#: lib/music_library_web/components/core_components.ex
#, elixir-autogen, elixir-format
msgid "Error!"
msgstr ""
#: lib/music_library_web/components/form_component.ex
#, elixir-autogen, elixir-format
msgid "Format"
@@ -73,11 +68,6 @@ msgstr ""
msgid "Genres"
msgstr ""
#: lib/music_library_web/components/core_components.ex
#, elixir-autogen, elixir-format
msgid "Hang in there while we get back on track"
msgstr ""
#: lib/music_library_web/live/collection_live/show.html.heex
#: lib/music_library_web/live/wishlist_live/show.html.heex
#, elixir-autogen, elixir-format
@@ -186,22 +176,12 @@ msgstr ""
msgid "Show"
msgstr ""
#: lib/music_library_web/components/core_components.ex
#, elixir-autogen, elixir-format
msgid "Something went wrong!"
msgstr ""
#: lib/music_library_web/components/layouts/app.html.heex
#: lib/music_library_web/live/stats_live/index.ex
#, elixir-autogen, elixir-format
msgid "Stats"
msgstr ""
#: lib/music_library_web/components/core_components.ex
#, elixir-autogen, elixir-format
msgid "Success!"
msgstr ""
#: lib/music_library_web/hooks/static_assets.ex
#, elixir-autogen, elixir-format
msgid "The application has been updated, please reload."
@@ -256,11 +236,6 @@ msgstr ""
msgid "You must be logged in to access this page"
msgstr ""
#: lib/music_library_web/components/core_components.ex
#, elixir-autogen, elixir-format
msgid "close"
msgstr ""
#: lib/music_library_web/live/artist_live/show.html.heex
#: lib/music_library_web/live/collection_live/show.html.heex
#: lib/music_library_web/live/wishlist_live/show.html.heex
@@ -805,11 +780,6 @@ msgstr ""
msgid "Scrobble disc"
msgstr ""
#: lib/music_library_web/components/core_components.ex
#, elixir-autogen, elixir-format
msgid "Warning!"
msgstr ""
#: lib/music_library_web/components/layouts/app.html.heex
#, elixir-autogen, elixir-format
msgid "More"
-30
View File
@@ -52,11 +52,6 @@ msgstr ""
msgid "Error importing record"
msgstr ""
#: lib/music_library_web/components/core_components.ex
#, elixir-autogen, elixir-format
msgid "Error!"
msgstr ""
#: lib/music_library_web/components/form_component.ex
#, elixir-autogen, elixir-format
msgid "Format"
@@ -73,11 +68,6 @@ msgstr ""
msgid "Genres"
msgstr ""
#: lib/music_library_web/components/core_components.ex
#, elixir-autogen, elixir-format
msgid "Hang in there while we get back on track"
msgstr ""
#: lib/music_library_web/live/collection_live/show.html.heex
#: lib/music_library_web/live/wishlist_live/show.html.heex
#, elixir-autogen, elixir-format
@@ -186,22 +176,12 @@ msgstr ""
msgid "Show"
msgstr ""
#: lib/music_library_web/components/core_components.ex
#, elixir-autogen, elixir-format
msgid "Something went wrong!"
msgstr ""
#: lib/music_library_web/components/layouts/app.html.heex
#: lib/music_library_web/live/stats_live/index.ex
#, elixir-autogen, elixir-format
msgid "Stats"
msgstr ""
#: lib/music_library_web/components/core_components.ex
#, elixir-autogen, elixir-format
msgid "Success!"
msgstr ""
#: lib/music_library_web/hooks/static_assets.ex
#, elixir-autogen, elixir-format
msgid "The application has been updated, please reload."
@@ -256,11 +236,6 @@ msgstr ""
msgid "You must be logged in to access this page"
msgstr ""
#: lib/music_library_web/components/core_components.ex
#, elixir-autogen, elixir-format
msgid "close"
msgstr ""
#: lib/music_library_web/live/artist_live/show.html.heex
#: lib/music_library_web/live/collection_live/show.html.heex
#: lib/music_library_web/live/wishlist_live/show.html.heex
@@ -805,11 +780,6 @@ msgstr ""
msgid "Scrobble disc"
msgstr ""
#: lib/music_library_web/components/core_components.ex
#, elixir-autogen, elixir-format
msgid "Warning!"
msgstr ""
#: lib/music_library_web/components/layouts/app.html.heex
#, elixir-autogen, elixir-format
msgid "More"