defmodule PetalComponents.Button do use Phoenix.Component alias PetalComponents.Loading alias PetalComponents.Link import PetalComponents.Icon attr :size, :string, default: "md", values: ["xs", "sm", "md", "lg", "xl"], doc: "button sizes" attr :radius, :string, default: "md", values: ["none", "sm", "md", "lg", "xl", "full"], doc: "button border radius" attr :variant, :string, default: "solid", values: ["solid", "light", "outline", "inverted", "shadow", "ghost"], doc: "button variant" attr :color, :string, default: "primary", values: [ "primary", "secondary", "info", "success", "warning", "danger", "gray", "pure_white", "white", "light", "dark" ], doc: "button color" attr :to, :string, default: nil, doc: "link path" attr :loading, :boolean, default: false, doc: "indicates a loading state" attr :disabled, :boolean, default: false, doc: "indicates a disabled state" attr :icon, :any, default: nil, doc: "name of a Heroicon at the front of the button" attr :with_icon, :boolean, default: false, doc: "adds some icon base classes" attr :link_type, :string, default: "button", values: ["a", "live_patch", "live_redirect", "button"] attr :class, :any, default: nil, doc: "CSS class" attr :label, :string, default: nil, doc: "labels your button" attr :rest, :global, include: ~w(method download hreflang ping referrerpolicy rel target type value name form) slot :inner_block, required: false def button(assigns) do assigns = assigns |> assign(:classes, button_classes(assigns)) ~H""" <%= if @loading do %> <% else %> <%= if @icon do %> <.icon name={@icon} class={"pc-button__spinner-icon--#{@size}"} /> <% end %> <% end %> {render_slot(@inner_block) || @label} """ end attr :size, :string, default: "sm", values: ["xs", "sm", "md", "lg", "xl"] attr :color, :string, default: "gray", values: [ "primary", "secondary", "info", "success", "warning", "danger", "gray" ] attr :radius, :string, default: "full", values: ["none", "sm", "md", "lg", "xl", "full"], doc: "button radius" attr :to, :string, default: nil, doc: "link path" attr :loading, :boolean, default: false, doc: "indicates a loading state" attr :disabled, :boolean, default: false, doc: "indicates a disabled state" attr :with_icon, :boolean, default: false, doc: "adds some icon base classes" attr :link_type, :string, default: "button", values: ["a", "live_patch", "live_redirect", "button"] attr :class, :any, default: nil, doc: "CSS class" attr :tooltip, :string, default: nil, doc: "tooltip text" attr :rest, :global, include: ~w(method download hreflang ping referrerpolicy rel target type value name form) slot :inner_block, required: false def icon_button(assigns) do ~H""" <%= if @loading do %> <% else %> {render_slot(@inner_block)} <% end %> """ end defp button_classes(assigns) do size = assigns[:size] || "md" radius = assigns[:radius] || "md" variant = assigns[:variant] || "solid" color = assigns[:color] || "primary" loading = assigns[:loading] || false disabled = assigns[:disabled] || false with_icon = assigns[:with_icon] || assigns[:icon] || false user_classes = assigns[:class] || "" color_class = "pc-button--#{String.replace(color, "_", "-")}" variant_suffix = if variant == "solid", do: "", else: "-#{variant}" [ "pc-button", "#{color_class}#{variant_suffix}", "pc-button--#{size}", "pc-button--radius-#{radius}", user_classes, loading && "pc-button--loading", disabled && "pc-button--disabled", with_icon && "pc-button--with-icon" ] end end