Current section
Files
Jump to
Current section
Files
lib/components/buttons.ex
defmodule SigmaKit.Components.Buttons do
use Phoenix.LiveComponent
import SigmaKit.Components.Icons
@doc """
Renders a simple button component.
## Attributes
* `:class` - Additional CSS classes to apply to the button. Defaults to `nil`.
* `:primary` - A boolean indicating if the button should use the primary style. Defaults to `false`.
* `:light` - A boolean indicating if the button should use the light style. Defaults to `false`.
* `:danger` - A boolean indicating if the button should use the danger style. Defaults to `false`.
* `:inline` - A boolean indicating if the button should use the inline style. Defaults to `false`.
* `:rest` - A map of additional global attributes (e.g., `disabled`, `form`, `name`, `value`, `type`) to apply to the button.
## Slots
* `:inner_block` (required) - The content to render inside the button.
## Styles
The button supports multiple styles based on the attributes provided:
* `:primary`: A blue button with a hover effect.
* `:light`: A light gray button with a hover effect.
* `:danger`: A red button for destructive actions.
* `:inline`: A white button with a border and hover effects, suitable for inline usage.
"""
attr :class, :any, default: nil
attr :primary, :boolean, default: false
attr :light, :boolean, default: false
attr :danger, :boolean, default: false
attr :inline, :boolean, default: false
attr :rest, :global, include: ~w(type disabled form name value)
slot :inner_block, required: true
def button(assigns) do
~H"""
<button
class={[
"phx-submit-loading:opacity-75 rounded-lg ",
"text-sm font-semibold leading-6",
!@inline && "py-2 px-3",
!@primary && !@light && !@inline && !@danger &&
"bg-zinc-900 hover:bg-zinc-700 text-white active:text-white/80",
@primary && "bg-blue-900 hover:bg-blue-700 text-white",
@light && "bg-gray-200 hover:bg-gray-300 text-zinc-800",
@danger && "bg-red-700 text-zinc-50",
@inline &&
"px-3 py-1 bg-white hover:bg-gradient-to-t from-gray-100 to-20% to-white shadow border border-gray-200 hover:border-gray-300 transition-all text-zinc-600 hover:text-zinc-800",
@class
]}
{@rest}
>
{render_slot(@inner_block)}
</button>
"""
end
@doc """
Renders a toggle switch with icons on the left and right sides.
## Attributes
- `:left_icon` (string, required): The name of the icon to display on the left side of the toggle switch.
- `:right_icon` (string, required): The name of the icon to display on the right side of the toggle switch.
- `:event` (string, required): The event name triggered when the toggle switch is clicked.
- `:target` (optional): The target for the `phx-click` event.
- `:left` (boolean, required): Determines if the toggle is in the "left" position.
- `:right` (boolean, required): Determines if the toggle is in the "right" position.
"""
attr :left_icon, :string, required: true
attr :right_icon, :string, required: true
attr :event, :string, required: true
attr :target, :any, default: nil
attr :left, :boolean, required: true
attr :right, :boolean, required: true
def icon_toggle_switch(assigns) do
~H"""
<div class="flex gap-2 items-center cursor-pointer" phx-click="toggle-view" phx-target={@target}>
<.icon name={@left_icon} class={["w-5 h-5", !@left && "text-zinc-300"]} />
<div class={[
"h-6 w-12 bg-gray-100 shadow-inner rounded-full flex items-center px-2",
@left && "justify-start",
@right && "justify-end",
!@left && !@right && "justify-center"
]}>
<div class="w-4 h-4 rounded-full bg-blue-500"></div>
</div>
<.icon name={@right_icon} class={["w-5 h-5", !@right && "text-zinc-300"]} />
</div>
"""
end
@doc """
Renders a dropdown button with a customizable label and a list of actions.
## Attributes
- `:label` (string, optional): The label displayed on the dropdown button.
- `:id` (string, required): A unique identifier for the dropdown component.
## Slots
- `:action`: Defines the actions available in the dropdown menu. Each action can have the following attributes:
- `:label` (string, optional): The label for the action.
- `:icon` (string, optional): The name of the icon to display next to the action.
- `:event` (string, optional): The event triggered when the action is clicked.
- `:target` (any, optional): The target for the `phx-click` event.
- `:value` (any, optional): The value passed with the `phx-click` event.
"""
attr :label, :string
attr :id, :string, required: true
slot :action do
attr :label, :string
attr :icon, :string
attr :event, :string
attr :target, :any
attr :value, :any
end
def dropdown(assigns) do
~H"""
<.button
inline
type="button"
data-dropdown-toggle={"dropdown-#{@id}"}
data-dropdown-trigger="hover"
data-dropdown-delay={0}
data-dropdown-offset-distance={0}
data-dropdown-placement="bottom"
>
{@label}
<.icon name="hero-chevron-down" class="ms-2 h-3 w-3" />
</.button>
<div
class="z-50 hidden my-4 text-base list-none divide-y rounded-lg shadow bg-gray-50 divide-gray-200 overflow-hidden"
id={"dropdown-#{@id}"}
>
<ul class="divide-y divide-gray-200">
<li :for={action <- @action}>
<.link
phx-click={action[:event]}
phx-target={action[:target]}
phx-value-value={action[:value]}
class="px-4 block text-sm hover:bg-gray-200 text-zinc-800 text-nowrap font-medium flex items-center"
>
<div :if={action[:icon]} class="me-2 border-r py-2">
<.icon name={action.icon} class="w-4 h-4 me-2" />
</div>
<div class="py-2">
{action.label}
</div>
</.link>
</li>
</ul>
</div>
"""
end
end