defmodule PineUi.Button do
@moduledoc """
Provides button components with various styles and states.
The Button module offers primary, secondary, and danger button variants
with support for loading states, icons, and Phoenix LiveView integration.
## Examples
Submit
Cancel
Delete
## Accessibility
All button components provide proper focus states, ARIA attributes, and
keyboard interaction support.
"""
use Phoenix.Component
import Phoenix.HTML # This is needed for HTML markup
import Phoenix.HTML.Form # This is needed for form elements
@doc """
Renders a primary button component with optional loading state.
## Examples
<.primary>Submit
<.primary loading={true} phx_click="save" disabled={@form_invalid}>
Save Changes
<.primary icon="">
With Icon
## Options
* `:type` - Button type attribute (optional, defaults to "button")
* `:class` - Additional CSS classes (optional)
* `:disabled` - Whether the button is disabled (optional, defaults to false)
* `:loading` - Whether to show loading state (optional, defaults to false)
* `:icon` - HTML string for an icon to display before text (optional)
* `:phx_click` - The LiveView click event to trigger (optional)
* `:phx_value_id` - The id value to pass with the event (optional)
* `:phx_target` - The LiveView target for the event (optional)
"""
def primary(assigns) do
assigns =
assigns
|> assign_new(:type, fn -> "button" end)
|> assign_new(:class, fn -> "" end)
|> assign_new(:disabled, fn -> false end)
|> assign_new(:loading, fn -> false end)
|> assign_new(:phx_click, fn -> nil end)
|> assign_new(:phx_value_id, fn -> nil end)
|> assign_new(:phx_target, fn -> nil end)
|> assign_new(:icon, fn -> nil end)
~H"""
"""
end
@doc """
Renders a secondary button component with optional loading state.
Secondary buttons are often used for secondary actions or alternative options.
## Examples
<.secondary>Cancel
<.secondary loading={@processing} phx_click="back">
Go Back
## Options
* `:type` - Button type attribute (optional, defaults to "button")
* `:class` - Additional CSS classes (optional)
* `:disabled` - Whether the button is disabled (optional, defaults to false)
* `:loading` - Whether to show loading state (optional, defaults to false)
* `:icon` - HTML string for an icon to display before text (optional)
* `:phx_click` - The LiveView click event to trigger (optional)
* `:phx_value_id` - The id value to pass with the event (optional)
* `:phx_target` - The LiveView target for the event (optional)
"""
def secondary(assigns) do
assigns =
assigns
|> assign_new(:type, fn -> "button" end)
|> assign_new(:class, fn -> "" end)
|> assign_new(:disabled, fn -> false end)
|> assign_new(:loading, fn -> false end)
|> assign_new(:phx_click, fn -> nil end)
|> assign_new(:phx_value_id, fn -> nil end)
|> assign_new(:phx_target, fn -> nil end)
|> assign_new(:icon, fn -> nil end)
~H"""
"""
end
@doc """
Renders a danger button component with optional loading state.
Danger buttons should be used for destructive actions such as delete or remove.
## Examples
<.danger>Delete Account
<.danger loading={@deleting} phx_click="delete" phx_value_id={@item.id}>
Remove Item
## Options
* `:type` - Button type attribute (optional, defaults to "button")
* `:class` - Additional CSS classes (optional)
* `:disabled` - Whether the button is disabled (optional, defaults to false)
* `:loading` - Whether to show loading state (optional, defaults to false)
* `:icon` - HTML string for an icon to display before text (optional)
* `:phx_click` - The LiveView click event to trigger (optional)
* `:phx_value_id` - The id value to pass with the event (optional)
* `:phx_target` - The LiveView target for the event (optional)
"""
def danger(assigns) do
assigns =
assigns
|> assign_new(:type, fn -> "button" end)
|> assign_new(:class, fn -> "" end)
|> assign_new(:disabled, fn -> false end)
|> assign_new(:loading, fn -> false end)
|> assign_new(:phx_click, fn -> nil end)
|> assign_new(:phx_value_id, fn -> nil end)
|> assign_new(:phx_target, fn -> nil end)
|> assign_new(:icon, fn -> nil end)
~H"""
"""
end
end