Packages
petal_components
3.2.0
4.7.0
4.6.2
4.6.1
4.6.0
4.5.0
4.4.0
4.3.0
4.2.1
4.2.0
4.1.2
4.1.1
4.1.0
4.0.12
4.0.11
4.0.10
4.0.6
4.0.5
4.0.4
4.0.3
4.0.1
3.2.2
3.2.1
3.2.0
3.1.0
3.0.2
3.0.1
3.0.0
2.9.3
2.9.2
retired
2.9.1
retired
2.9.0
retired
2.8.4
2.8.3
2.8.2
2.8.1
2.8.0
2.7.4
2.7.3
2.7.2
2.7.1
2.7.0
2.6.1
2.6.0
2.5.2
2.5.1
2.5.0
2.4.3
2.4.2
2.4.1
2.4.0
2.3.0
2.2.1
2.2.0
2.1.2
2.1.1
2.1.0
2.0.6
2.0.5
2.0.4
2.0.3
2.0.2
2.0.1
2.0.0
1.9.3
1.9.2
1.9.1
1.9.0
1.8.0
1.7.1
1.7.0
1.6.2
1.6.1
1.6.0
1.5.5
1.5.4
1.5.3
1.5.2
1.5.1
1.5.0
1.4.9
1.4.8
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.0
1.2.14
1.2.13
1.2.12
1.2.11
1.2.10
1.2.9
1.2.8
1.2.7
1.2.6
1.2.5
1.2.4
1.2.3
1.2.2
1.2.1
1.2.0
1.1.6
1.1.5
1.1.4
1.1.3
1.1.2
1.1.1
1.1.0
1.0.8
1.0.7
1.0.6
1.0.5
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0
0.19.10
0.19.9
0.19.8
0.19.7
0.19.6
0.19.5
0.19.4
0.19.3
0.19.2
0.19.1
0.19.0
0.18.5
0.18.4
0.18.3
0.18.2
0.18.1
0.18.0
0.17.7
0.17.6
0.17.5
0.17.4
0.17.3
0.17.2
0.17.1
0.17.0
0.16.0
0.15.0
0.14.1
0.14.0
0.13.7
0.13.6
0.13.5
0.13.4
0.13.3
0.13.2
0.13.1
0.13.0
0.12.0
0.11.4
0.11.3
0.11.2
0.11.1
0.11.0
0.10.8
0.10.7
0.10.6
0.10.5
0.10.4
0.10.3
0.10.2
0.10.1
0.10.0
0.9.3
0.9.2
0.9.1
0.9.0
0.8.0
0.7.0
0.6.1
0.6.0
0.5.1
0.5.0
0.4.0
0.3.2
0.3.1
0.3.0
0.2.2
0.2.1
0.2.0
0.1.0
Shadcn-style Phoenix LiveView components that AI assistants can actually use. Pair with the MCP server so AI coding tools can inspect the real component API.
Current section
Files
Jump to
Current section
Files
lib/petal_components/alert.ex
defmodule PetalComponents.Alert do
use Phoenix.Component
alias Phoenix.LiveView.JS
alias PetalComponents.Helpers
import PetalComponents.Icon
attr(:color, :string,
default: "info",
values: ["info", "success", "warning", "danger"]
)
attr(:variant, :string,
default: "light",
values: ["light", "soft", "dark", "outline"],
doc: "The variant of the alert"
)
attr(:with_icon, :boolean, default: false, doc: "adds some icon base classes")
attr(:class, :any, default: nil, doc: "CSS class for parent div")
attr(:heading, :string, default: nil, doc: "label your heading")
attr(:label, :string, default: nil, doc: "label your alert")
attr(:rest, :global)
attr(:close_button_properties, :list,
default: nil,
doc: "a list of properties passed to the close button"
)
attr :on_dismiss, JS,
default: %JS{},
doc:
"JS commands to run when the alert is dismissed. Automatically adds a close button with built-in hide behavior."
slot(:inner_block)
def alert(assigns) do
assigns =
assigns
|> assign(:classes, alert_classes(assigns))
|> assign(:heading_id, Helpers.uniq_id(assigns.heading || "alert-heading"))
|> assign(:label_id, Helpers.uniq_id(assigns.label || "alert-label"))
|> assign_new(:alert_id, fn -> "alert-#{System.unique_integer([:positive])}" end)
~H"""
<%= unless label_blank?(@label, @inner_block) do %>
<div
{@rest}
id={@alert_id}
class={@classes}
role="dialog"
aria-labelledby={(@heading && @heading_id) || @label_id}
aria-describedby={@label_id}
>
<%= if @with_icon do %>
<div class="pc-alert__icon-container">
<.get_icon color={@color} />
</div>
<% end %>
<div class="pc-alert">
<div class="pc-alert__inner">
<div>
<%= if @heading do %>
<h2 id={@heading_id} class="pc-alert__heading">
{@heading}
</h2>
<% end %>
<div id={@label_id} class="pc-alert__label">
{render_slot(@inner_block) || @label}
</div>
</div>
<%= if @on_dismiss.ops != [] do %>
<button
class={["pc-alert__dismiss-button", get_dismiss_icon_classes(@color, @variant)]}
phx-click={
Helpers.compose_js(
@on_dismiss,
JS.hide(
to: "##{@alert_id}",
transition:
{"ease-out duration-300", "opacity-100", "opacity-0"}
)
)
}
>
<.icon name="hero-x-mark-solid" class="self-start w-4 h-4" />
</button>
<% else %>
<%= if @close_button_properties do %>
<button
class={["pc-alert__dismiss-button", get_dismiss_icon_classes(@color, @variant)]}
{@close_button_properties}
>
<.icon name="hero-x-mark-solid" class="self-start w-4 h-4" />
</button>
<% end %>
<% end %>
</div>
</div>
</div>
<% end %>
"""
end
defp alert_classes(opts) do
opts = %{
color: opts[:color] || "info",
variant: opts[:variant] || "light",
class: opts[:class] || ""
}
base_classes = "pc-alert-base-classes"
color_css = get_color_classes(opts.color, opts.variant)
custom_classes = opts.class
[base_classes, color_css, custom_classes]
end
defp get_color_classes(color, variant) do
"pc-alert--#{color}-#{variant}"
end
defp get_dismiss_icon_classes(color, variant) do
"pc-alert__dismiss-button--#{color}-#{variant}"
end
defp get_icon(%{color: "info"} = assigns) do
~H"""
<.icon name="hero-information-circle" />
"""
end
defp get_icon(%{color: "success"} = assigns) do
~H"""
<.icon name="hero-check-circle" />
"""
end
defp get_icon(%{color: "warning"} = assigns) do
~H"""
<.icon name="hero-exclamation-circle" />
"""
end
defp get_icon(%{color: "danger"} = assigns) do
~H"""
<.icon name="hero-x-circle" />
"""
end
defp label_blank?(label, inner_block) do
(!label || label == "") && inner_block == []
end
end