Packages
petal_components
0.9.1
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 PetalComponents.Heroicons
# prop state, :string, options: ["info", "success", "warning", "danger"]
# prop class, :css_class
# prop label, :string
# slot default
def alert(assigns) do
assigns = assigns
|> assign_new(:label, fn -> nil end)
|> assign_new(:state, fn -> "info" end)
|> assign_new(:heading, fn -> nil end)
|> assign_new(:inner_block, fn -> nil end)
|> assign_new(:classes, fn -> alert_classes(assigns) end)
~H"""
<%= unless label_blank?(@label, @inner_block) do %>
<div class={@classes}>
<div class="flex-shrink-0">
<Heroicons.Outline.render icon={get_icon(@state)} />
</div>
<div class="flex-0">
<%= if @heading do %>
<div class="mb-2 font-bold"><%= @heading %></div>
<% end %>
<%= if @inner_block do %>
<%= render_slot(@inner_block) %>
<% else %>
<%= @label %>
<% end %>
</div>
</div>
<% end %>
"""
end
defp alert_classes(opts) do
opts = %{
state: opts[:state] || "info",
class: opts[:class] || "",
}
base_classes = "w-full flex text-sm rounded-xl justify-start focus:outline-none font-medium leading-6 px-4 py-2 gap-3"
state_css = get_state_classes(opts.state)
custom_classes = opts.class
[
base_classes,
state_css,
custom_classes
]
|> Enum.join(" ")
end
defp get_state_classes("info"), do: "text-blue-600 bg-blue-100 dark:bg-[#071418] dark:text-blue-200"
defp get_state_classes("success"), do: "text-green-600 bg-green-100 dark:bg-[#0C130D] dark:text-green-200"
defp get_state_classes("warning"), do: "text-yellow-600 bg-yellow-100 dark:bg-[#191207] dark:text-yellow-200"
defp get_state_classes("danger"), do: "text-red-600 bg-red-100 dark:bg-[#160B0B] dark:text-red-200"
defp get_icon("info"), do: :information_circle
defp get_icon("success"), do: :check_circle
defp get_icon("warning"), do: :exclamation_circle
defp get_icon("danger"), do: :x_circle
defp label_blank?(label, inner_block) do
(!label || label == "") && !inner_block
end
end