diff --git a/.formatter.exs b/.formatter.exs index 1b2af96..b8d13c5 100644 --- a/.formatter.exs +++ b/.formatter.exs @@ -1,6 +1,6 @@ [ import_deps: [:phoenix], - plugins: [Phoenix.LiveView.HTMLFormatter, Styler], + plugins: [Phoenix.LiveView.HTMLFormatter, Quokka], inputs: ["{mix,.formatter}.exs", "*.{heex,ex,exs}", "{config,lib,test}/**/*.{heex,ex,exs}"], subdirectories: ["demo"] ] diff --git a/README.md b/README.md index 0549aac..835123d 100644 --- a/README.md +++ b/README.md @@ -277,6 +277,13 @@ msgstr "Aguanta mientras volvemos a la normalidad" component-specific presentation or behavior without adding library-level options. LiveToast does not interpret metadata. +### Custom rendering and classes + +The `component` option and `toast_component_fn` render the content inside a LiveToast-managed toast shell. The shell +continues to provide the hook, timing attributes, enter and exit animations, stacking, and dismiss button. Use +[`toast_class_fn/1`](https://hexdocs.pm/live_toast/LiveToast.html#toast_class_fn/1) to change that outer shell's +classes; use a custom component function for the icon, title, body, action, and other toast content. + ### Default custom toast component Pass `toast_component_fn` to `LiveToast.toast_group` when all programmatic toasts in that host should use the same diff --git a/config/config.exs b/config/config.exs index 2103d99..2abdeee 100644 --- a/config/config.exs +++ b/config/config.exs @@ -1,8 +1,9 @@ import Config -config :phoenix, :json_library, Jason -config :logger, :level, :debug config :logger, :backends, [] +config :logger, :level, :debug + +config :phoenix, :json_library, Jason if Mix.env() == :dev do esbuild = fn args -> diff --git a/demo/.formatter.exs b/demo/.formatter.exs index 2e6e73e..da90261 100644 --- a/demo/.formatter.exs +++ b/demo/.formatter.exs @@ -1,5 +1,5 @@ [ import_deps: [:phoenix], - plugins: [Phoenix.LiveView.HTMLFormatter, Styler], + plugins: [Phoenix.LiveView.HTMLFormatter, Quokka], inputs: ["{mix,.formatter}.exs", "*.{heex,ex,exs}", "{config,lib,test}/**/*.{heex,ex,exs}"] ] diff --git a/demo/config/config.exs b/demo/config/config.exs index 92ae11b..54e6200 100644 --- a/demo/config/config.exs +++ b/demo/config/config.exs @@ -1,27 +1,10 @@ import Config -config :esbuild, - version: "0.17.11", - demo: [ - args: ~w(js/app.js --bundle --target=es2017 --outdir=../priv/static/assets --external:/fonts/* --external:/images/*), - cd: Path.expand("../assets", __DIR__), - env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)} - ] - -config :tailwind, - version: "3.4.0", - demo: [ - args: ~w( - --config=tailwind.config.cjs - --input=css/app.css - --output=../priv/static/assets/app.css - ), - cd: Path.expand("../assets", __DIR__) - ] +alias Phoenix.Endpoint.Cowboy2Adapter config :demo, DemoWeb.Endpoint, url: [host: "localhost"], - adapter: Phoenix.Endpoint.Cowboy2Adapter, + adapter: Cowboy2Adapter, render_errors: [ formats: [html: DemoWeb.ErrorHTML, json: DemoWeb.ErrorJSON], layout: false @@ -29,6 +12,15 @@ config :demo, DemoWeb.Endpoint, pubsub_server: Demo.PubSub, live_view: [signing_salt: "mca0adK+"] +config :esbuild, + version: "0.17.11", + demo: [ + args: + ~w(js/app.js --bundle --target=es2017 --outdir=../priv/static/assets --external:/fonts/* --external:/images/*), + cd: Path.expand("../assets", __DIR__), + env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)} + ] + config :live_toast, gettext_backend: Demo.Gettext @@ -38,4 +30,15 @@ config :logger, :console, config :phoenix, :json_library, Jason +config :tailwind, + version: "3.4.0", + demo: [ + args: ~w( + --config=tailwind.config.cjs + --input=css/app.css + --output=../priv/static/assets/app.css + ), + cd: Path.expand("../assets", __DIR__) + ] + import_config "#{config_env()}.exs" diff --git a/demo/config/dev.exs b/demo/config/dev.exs index 2eab3ae..40ada74 100644 --- a/demo/config/dev.exs +++ b/demo/config/dev.exs @@ -1,5 +1,14 @@ import Config +config :demo, DemoWeb.Endpoint, + live_reload: [ + patterns: [ + ~r"priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$", + ~r"priv/gettext/.*(po)$", + ~r"lib/demo_web/(controllers|live|components)/.*(ex|heex)$" + ] + ] + config :demo, DemoWeb.Endpoint, reloadable_apps: [:live_toast, :demo], http: [ip: {127, 0, 0, 1}, port: 4004], @@ -12,15 +21,5 @@ config :demo, DemoWeb.Endpoint, tailwind: {Tailwind, :install_and_run, [:demo, ~w(--watch)]} ] -config :demo, DemoWeb.Endpoint, - live_reload: [ - patterns: [ - ~r"priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$", - ~r"priv/gettext/.*(po)$", - ~r"lib/demo_web/(controllers|live|components)/.*(ex|heex)$" - ] - ] - -config :phoenix, :stacktrace_depth, 20 - config :phoenix, :plug_init_mode, :runtime +config :phoenix, :stacktrace_depth, 20 diff --git a/demo/config/runtime.exs b/demo/config/runtime.exs index 47f0e90..12828e6 100644 --- a/demo/config/runtime.exs +++ b/demo/config/runtime.exs @@ -15,8 +15,6 @@ if config_env() == :prod do host = System.get_env("PHX_HOST") || "example.com" port = String.to_integer(System.get_env("PORT") || "4004") - config :demo, :dns_cluster_query, System.get_env("DNS_CLUSTER_QUERY") - config :demo, DemoWeb.Endpoint, url: [host: host, port: 443, scheme: "https"], http: [ @@ -24,4 +22,6 @@ if config_env() == :prod do port: port ], secret_key_base: secret_key_base + + config :demo, :dns_cluster_query, System.get_env("DNS_CLUSTER_QUERY") end diff --git a/demo/config/test.exs b/demo/config/test.exs index 8905546..eb49431 100644 --- a/demo/config/test.exs +++ b/demo/config/test.exs @@ -1,9 +1,10 @@ import Config -config :logger, level: :warning -config :phoenix, :plug_init_mode, :runtime - config :demo, DemoWeb.Endpoint, http: [ip: {127, 0, 0, 1}, port: 4002], secret_key_base: "C+Yn8zjDt2z+Sbl3NhLDra8U+J1QlqLoTSLx7w9BkToiWOnPk58H9nqTq+Y9OR3A", server: false + +config :logger, level: :warning + +config :phoenix, :plug_init_mode, :runtime diff --git a/demo/lib/demo_web/components/layouts.ex b/demo/lib/demo_web/components/layouts.ex index 6176546..27a66b5 100644 --- a/demo/lib/demo_web/components/layouts.ex +++ b/demo/lib/demo_web/components/layouts.ex @@ -29,7 +29,8 @@ defmodule DemoWeb.Layouts do "items-end bottom-0 left-1/2 transform -translate-x-1/2 flex-col-reverse sm:top-auto", assigns[:corner] == :bottom_right && "items-end bottom-0 right-0 flex-col-reverse sm:top-auto", assigns[:corner] == :top_left && "items-start top-0 left-0 flex-col sm:bottom-auto", - assigns[:corner] == :top_center && "items-start top-0 left-1/2 transform -translate-x-1/2 flex-col sm:bottom-auto", + assigns[:corner] == :top_center && + "items-start top-0 left-1/2 transform -translate-x-1/2 flex-col sm:bottom-auto", assigns[:corner] == :top_right && "items-start top-0 right-0 flex-col sm:bottom-auto" ] end diff --git a/demo/lib/demo_web/endpoint.ex b/demo/lib/demo_web/endpoint.ex index 54ce653..f790599 100644 --- a/demo/lib/demo_web/endpoint.ex +++ b/demo/lib/demo_web/endpoint.ex @@ -1,6 +1,8 @@ defmodule DemoWeb.Endpoint do use Phoenix.Endpoint, otp_app: :demo + alias Phoenix.LiveView.Socket + @session_options [ store: :cookie, key: "_demo_key", @@ -8,7 +10,7 @@ defmodule DemoWeb.Endpoint do same_site: "Lax" ] - socket("/live", Phoenix.LiveView.Socket, + socket("/live", Socket, websocket: [connect_info: [session: @session_options]], longpoll: [connect_info: [session: @session_options]] ) diff --git a/demo/lib/demo_web/live/home_live.ex b/demo/lib/demo_web/live/home_live.ex index 8046fa2..95b4f74 100644 --- a/demo/lib/demo_web/live/home_live.ex +++ b/demo/lib/demo_web/live/home_live.ex @@ -203,7 +203,7 @@ defmodule DemoWeb.HomeLive do end duration = - case Map.get(payload, "duration", nil) do + case Map.get(payload, "duration") do d when is_integer(d) -> d d when is_binary(d) -> String.to_integer(d) _ -> nil diff --git a/demo/lib/demo_web/live/tabs/customization.html.heex b/demo/lib/demo_web/live/tabs/customization.html.heex index 5f02c95..926ccfd 100644 --- a/demo/lib/demo_web/live/tabs/customization.html.heex +++ b/demo/lib/demo_web/live/tabs/customization.html.heex @@ -31,7 +31,7 @@
- If you need more control over the styles, you can also pass a custom class function (that generates the class string for the main element). Note that there are a lot of required things in the default implementation of this class. It is best to take the example from the docs and extend it rather than start from zero. + A custom class function changes the outer toast shell, which owns the LiveToast hook, timing, animation, and dismiss button. Note that there are a lot of required things in the default implementation of this class. It is best to take the example from the docs and extend it rather than start from zero.
- If you need total control, you can pass a custom component to the toast functions. This hijacks the normal rendering and then you can pretty much do whatever you want in terms of generating the DOM elements.
+ A custom component renders the toast content inside the LiveToast shell. Use it to control the icon, title, body, actions, and application-specific markup while LiveToast continues to manage timing, animation, and dismissal. Pass it to an individual toast, or define
+ toast_component_fn
+ on toast_group
+ to use it for every programmatic toast in that host.