Current section
Files
Jump to
Current section
Files
lib/daisyui_components/core_components.ex
defmodule DaisyUIComponents.CoreComponents do
@moduledoc """
UI components from [Phoenix Core Components](https://github.com/phoenixframework/phoenix/blob/main/installer/templates/phx_web/components/core_components.ex).
The components were modified to fit DaisyUI components
"""
use DaisyUIComponents.Component
import DaisyUIComponents.Icon
import DaisyUIComponents.Table
@doc """
Renders a simple form.
## Examples
<.simple_form for={@form} phx-change="validate" phx-submit="save">
<.input field={@form[:email]} label="Email"/>
<.input field={@form[:username]} label="Username" />
<:actions>
<.button>Save</.button>
</:actions>
</.simple_form>
"""
attr :for, :any, required: true, doc: "the datastructure for the form"
attr :as, :any, default: nil, doc: "the server side parameter to collect all input under"
attr :rest, :global,
include: ~w(autocomplete name rel action enctype method novalidate target),
doc: "the arbitrary HTML attributes to apply to the form tag"
slot :inner_block, required: true
slot :actions, doc: "the slot for form actions, such as a submit button"
def simple_form(assigns) do
~H"""
<.form :let={f} for={@for} as={@as} {@rest}>
<div class="mt-10 space-y-8">
<%= render_slot(@inner_block, f) %>
<div :for={action <- @actions} class="mt-2 flex items-center justify-between gap-6">
<%= render_slot(action, f) %>
</div>
</div>
</.form>
"""
end
@doc """
Renders a header with title.
"""
attr :class, :string, default: nil
slot :inner_block, required: true
slot :subtitle
slot :actions
def header(assigns) do
~H"""
<header class={[@actions != [] && "flex items-center justify-between gap-6", @class]}>
<div>
<h1 class="text-lg font-semibold leading-8">
<%= render_slot(@inner_block) %>
</h1>
<p :if={@subtitle != []} class="mt-2 text-sm leading-6">
<%= render_slot(@subtitle) %>
</p>
</div>
<div class="flex-none"><%= render_slot(@actions) %></div>
</header>
"""
end
@doc ~S"""
Renders a table with generic styling.
## Examples
<.simple_table id="users" rows={@users}>
<:col :let={user} label="id"><%= user.id %></:col>
<:col :let={user} label="username"><%= user.username %></:col>
</.simple_table>
"""
attr :id, :string, required: true
attr :rows, :list, required: true
attr :row_id, :any, default: nil, doc: "the function for generating the row id"
attr :row_click, :any, default: nil, doc: "the function for handling phx-click on each row"
attr :row_item, :any,
default: &Function.identity/1,
doc: "the function for mapping each row before calling the :col and :action slots"
slot :col, required: true do
attr :label, :string
end
slot :action, doc: "the slot for showing user actions in the last table column"
def simple_table(assigns) do
assigns =
with %{rows: %Phoenix.LiveView.LiveStream{}} <- assigns do
assign(assigns, row_id: assigns.row_id || fn {id, _item} -> id end)
end
~H"""
<.table>
<.thead>
<.tr>
<.th :for={col <- @col}><%= col[:label] %></.th>
<.th>
<span class="sr-only"><span class="sr-only"><%= translate("Actions") %></span></span>
</.th>
</.tr>
</.thead>
<.tbody id={@id} phx-update={match?(%Phoenix.LiveView.LiveStream{}, @rows) && "stream"}>
<.tr :for={row <- @rows} id={@row_id && @row_id.(row)}>
<.td
:for={col <- @col}
phx-click={@row_click && @row_click.(row)}
class={[@row_click && "hover:cursor-pointer"]}
>
<%= render_slot(col, @row_item.(row)) %>
</.td>
<.td :if={@action != []}>
<span :for={action <- @action}>
<%= render_slot(action, @row_item.(row)) %>
</span>
</.td>
</.tr>
</.tbody>
</.table>
"""
end
@doc """
Renders a data list.
## Examples
<.list>
<:item title="Title"><%= @post.title %></:item>
<:item title="Views"><%= @post.views %></:item>
</.list>
"""
slot :item, required: true do
attr :title, :string, required: true
end
def list(assigns) do
~H"""
<div class="mt-14">
<dl class="-my-4 divide-y">
<div :for={item <- @item} class="flex gap-4 py-4 text-sm leading-6 sm:gap-8">
<dt class="w-1/4 flex-none"><%= item.title %></dt>
<dd><%= render_slot(item) %></dd>
</div>
</dl>
</div>
"""
end
@doc """
Renders a back navigation link.
## Examples
<.back navigate={~p"/posts"}>Back to posts</.back>
"""
attr :navigate, :any, required: true
slot :inner_block, required: true
def back(assigns) do
~H"""
<div class="mt-16">
<.link navigate={@navigate} class="text-sm font-semibold leading-6">
<.icon name="hero-arrow-left-solid" class="h-3 w-3" />
<%= render_slot(@inner_block) %>
</.link>
</div>
"""
end
end