Skip to content

Commit

Permalink
feature: customize container classes
Browse files Browse the repository at this point in the history
  • Loading branch information
srcrip committed Jul 6, 2024
1 parent 734f255 commit f1d86a1
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 63 deletions.
7 changes: 5 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,8 @@ Releasing new bundle (meant to compile it in `v0.6.1`).
- Documentation updates.
- Fixes invalid usage of Phoenix LiveView streams by moving the flashes outside the stream container.
- Fixes a bit of a visual issue when loading on non LV pages by setting opacity to 0.
- New feature: arbitrary severity levels other than `:info` and `:error`
- Various refactorings and cleanups
- New feature: arbitrary severity levels other than `:info` and `:error`.
- Various refactorings and cleanups.
- Fix required LV version to 0.20.
- Added proper TypeScript types.
- Added customization for the container class.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ some of the methods below to support that.

### Custom Classes

You can define a custom toast class function, like so:
You can define a [custom toast class function](https://hexdocs.pm/live_toast/LiveToast.html#toast_class_fn/1), like so:

```elixir
defmodule MyModule do
Expand All @@ -198,6 +198,8 @@ And then use it to override the default styles:
<LiveToast.toast_group flash={@flash} connected={assigns[:socket] != nil} toast_class_fn={&MyModule.toast_class_fn/1} />
```

If you need to change the classes of the container, there is a similar function parameter called [`group_class_fn`](https://hexdocs.pm/live_toast/LiveToast.html#group_class_fn/1). Reference the documentation and apply the override just as you would `toast_class_fn/1` shown above.

### Custom Severity Levels

New Phoenix projects [use `:info` and `:error`](https://hexdocs.pm/phoenix/controllers.html#flash-messages)
Expand Down
12 changes: 12 additions & 0 deletions demo/lib/demo_web/components/layouts.ex
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,16 @@ defmodule DemoWeb.Layouts do
assigns[:kind] == :warn && "!text-amber-700 !bg-amber-100 border-amber-200"
]
end

def demo_group_class_fn(assigns) do
[
# base classes
"fixed z-50 max-h-screen w-full p-4 md:max-w-[420px] pointer-events-none grid origin-center",
# classes to set container positioning
assigns[:corner] == :bottom_left && "items-end bottom-0 left-0 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_right && "items-start top-0 right-0 flex-col sm:bottom-auto"
]
end
end
1 change: 1 addition & 0 deletions demo/lib/demo_web/components/layouts/app.html.heex
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<div class="grow p-3 md:p-6 mx-auto max-screen-4xl">
<LiveToast.toast_group
toast_class_fn={&demo_toast_class_fn/1}
group_class_fn={&demo_group_class_fn/1}
flash={@flash}
kinds={[:info, :error, :warn]}
connected={assigns[:socket] != nil}
Expand Down
49 changes: 48 additions & 1 deletion lib/live_toast.ex
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ defmodule LiveToast do
Then use it in your layout:
<LiveToast.toast_group flash={@flash} connected={assigns[:socket] != nil} toast_class_fn={MyModule.toast_class_fn/1} />
Since this is a public function, you can also write a new function that calls it and extends it's return values.
"""
def toast_class_fn(assigns) do
[
Expand All @@ -152,6 +154,44 @@ defmodule LiveToast do
]
end

@doc """
Default class function for the container around the toasts. Override this to change the classes of the toast container element.
## Examples:
defmodule MyModule do
def group_class_fn(assigns) do
[
# base classes
"fixed z-50 max-h-screen w-full p-4 md:max-w-[420px] pointer-events-none grid origin-center",
# classes to set container positioning
assigns[:corner] == :bottom_left && "items-end bottom-0 left-0 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_right && "items-start top-0 right-0 flex-col sm:bottom-auto"
]
end
end
Then use it in your layout:
<LiveToast.toast_group flash={@flash} connected={assigns[:socket] != nil} group_class_fn={MyModule.group_class_fn/1} />
Since this is a public function, you can also write a new function that calls it and extends it's return values.
"""
def group_class_fn(assigns) do
[
# base classes
"fixed z-50 max-h-screen w-full p-4 md:max-w-[420px] pointer-events-none grid origin-center",
# classes to set container positioning
assigns[:corner] == :bottom_left && "items-end bottom-0 left-0 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_right && "items-start top-0 right-0 flex-col sm:bottom-auto"
]
end

attr(:flash, :map, required: true, doc: "the map of flash messages")
attr(:id, :string, default: "toast-group", doc: "the optional id of flash container")
attr(:connected, :boolean, default: false, doc: "whether we're in a liveview or not")
Expand All @@ -163,9 +203,14 @@ defmodule LiveToast do
doc: "the corner to display the toasts"
)

attr(:group_class_fn, :any,
default: &__MODULE__.group_class_fn/1,
doc: "function to override the container classes"
)

attr(:toast_class_fn, :any,
default: &__MODULE__.toast_class_fn/1,
doc: "function to override the look of the toasts"
doc: "function to override the toast classes"
)

@doc """
Expand All @@ -181,6 +226,7 @@ defmodule LiveToast do
module={LiveToast.LiveComponent}
corner={@corner}
toast_class_fn={@toast_class_fn}
group_class_fn={@group_class_fn}
f={@flash}
kinds={@kinds}
/>
Expand All @@ -189,6 +235,7 @@ defmodule LiveToast do
id={@id}
corner={@corner}
toast_class_fn={@toast_class_fn}
group_class_fn={@group_class_fn}
flash={@flash}
kinds={@kinds}
/>
Expand Down
47 changes: 15 additions & 32 deletions lib/live_toast/components.ex
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ defmodule LiveToast.Components do
doc: "the time in milliseconds before the message is automatically dismissed"
)

attr(:class_fn, :any,
attr(:toast_class_fn, :any,
required: true,
doc: "function to override the look of the toasts"
doc: "function to override the toast classes"
)

attr(:corner, :atom, required: true, doc: "the corner to display the toasts")
Expand Down Expand Up @@ -51,7 +51,7 @@ defmodule LiveToast.Components do
phx-hook="LiveToast"
data-duration={@duration}
data-corner={@corner}
class={@class_fn.(assigns)}
class={@toast_class_fn.(assigns)}
{@rest}
>
<%= if @component do %>
Expand Down Expand Up @@ -116,7 +116,7 @@ defmodule LiveToast.Components do

attr(:toast_class_fn, :any,
default: &LiveToast.toast_class_fn/1,
doc: "function to override the look of the toasts"
doc: "function to override the toast classes"
)

attr(:kinds, :list, required: true, doc: "the valid severity level kinds")
Expand All @@ -128,7 +128,7 @@ defmodule LiveToast.Components do
:for={level <- @kinds}
data-component="flash"
corner={@corner}
class_fn={@toast_class_fn}
toast_class_fn={@toast_class_fn}
duration={0}
kind={level}
title={String.capitalize(to_string(level))}
Expand All @@ -139,7 +139,7 @@ defmodule LiveToast.Components do
<.toast
data-component="flash"
corner={@corner}
class_fn={@toast_class_fn}
toast_class_fn={@toast_class_fn}
id="client-error"
kind={:error}
title="We can't find the internet"
Expand All @@ -155,7 +155,7 @@ defmodule LiveToast.Components do
<.toast
data-component="flash"
corner={@corner}
class_fn={@toast_class_fn}
toast_class_fn={@toast_class_fn}
id="server-error"
kind={:error}
title="Something went wrong!"
Expand All @@ -172,46 +172,29 @@ defmodule LiveToast.Components do

attr(:flash, :map, required: true, doc: "the map of flash messages")
attr(:id, :string, default: "toast-group", doc: "the optional id of flash container")
attr(:kinds, :list, required: true, doc: "the valid severity level kinds")

attr(:corner, :atom,
values: [:top_left, :top_right, :bottom_left, :bottom_right],
default: :bottom_right,
doc: "the corner to display the toasts"
)

attr(:group_class_fn, :any,
default: &LiveToast.group_class_fn/1,
doc: "function to override the container classes"
)

attr(:toast_class_fn, :any,
default: &LiveToast.toast_class_fn/1,
doc: "function to override the look of the toasts"
doc: "function to override the toast classes"
)

attr(:kinds, :list, required: true, doc: "the valid severity level kinds")

# Used to render flashes-only on regular non-LV pages.
@doc false
def flash_group(assigns) do
# todo: move this to a common implementation
default_classes =
"fixed z-50 max-h-screen w-full p-4 md:max-w-[420px] pointer-events-none grid origin-center"

class =
case assigns[:corner] do
:bottom_left ->
"#{default_classes} items-end bottom-0 left-0 flex-col-reverse sm:top-auto"

:bottom_right ->
"#{default_classes} items-end bottom-0 right-0 flex-col-reverse sm:top-auto"

:top_left ->
"#{default_classes} items-start top-0 left-0 flex-col sm:bottom-auto"

:top_right ->
"#{default_classes} items-start top-0 right-0 flex-col sm:bottom-auto"
end

assigns = assign(assigns, :class, class)

~H"""
<div id={assigns[:id] || "flash-group"} class={@class}>
<div id={assigns[:id] || "flash-group"} class={@group_class_fn.(assigns)}>
<.flashes f={@flash} corner={@corner} toast_class_fn={@toast_class_fn} kinds={@kinds} />
</div>
"""
Expand Down
29 changes: 2 additions & 27 deletions lib/live_toast/live_component.ex
Original file line number Diff line number Diff line change
Expand Up @@ -36,33 +36,8 @@ defmodule LiveToast.LiveComponent do

@impl Phoenix.LiveComponent
def render(assigns) do
default_classes =
"fixed z-50 max-h-screen w-full p-4 md:max-w-[420px] pointer-events-none grid origin-center"

class =
case assigns[:corner] do
:bottom_left ->
"#{default_classes} items-end bottom-0 left-0 flex-col-reverse sm:top-auto"

:bottom_right ->
"#{default_classes} items-end bottom-0 right-0 flex-col-reverse sm:top-auto"

:top_left ->
"#{default_classes} items-start top-0 left-0 flex-col sm:bottom-auto"

:top_right ->
"#{default_classes} items-start top-0 right-0 flex-col sm:bottom-auto"
end

assigns = assign(assigns, :class, class)

~H"""
<div
id={assigns[:id] || "toast-group"}
class={[
@class
]}
>
<div id={assigns[:id] || "toast-group"} class={@group_class_fn.(assigns)}>
<div class="contents" id="toast-group-stream" phx-update="stream">
<Components.toast
:for={
Expand All @@ -81,7 +56,7 @@ defmodule LiveToast.LiveComponent do
data-count={@toast_count}
duration={duration}
kind={k}
class_fn={@toast_class_fn}
toast_class_fn={@toast_class_fn}
component={component}
icon={icon}
action={action}
Expand Down

0 comments on commit f1d86a1

Please sign in to comment.