defmodule MvWeb.CoreComponents do
@moduledoc """
Provides core UI components.
At first glance, this module may seem daunting, but its goal is to provide
core building blocks for your application, such as tables, forms, and
inputs. The components consist mostly of markup and are well-documented
with doc strings and declarative assigns. You may customize and style
them in any way you want, based on your application growth and needs.
The foundation for styling is Tailwind CSS, a utility-first CSS framework,
augmented with daisyUI, a Tailwind CSS plugin that provides UI components
and themes. Here are useful references:
* [daisyUI](https://daisyui.com/docs/intro/) - a good place to get
started and see the available components.
* [Tailwind CSS](https://tailwindcss.com) - the foundational framework
we build on. You will use it for layout, sizing, flexbox, grid, and
spacing.
* [Heroicons](https://heroicons.com) - see `icon/1` for usage.
* [Phoenix.Component](https://hexdocs.pm/phoenix_live_view/Phoenix.Component.html) -
the component system used by Phoenix. Some components, such as `<.link>`
and `<.form>`, are defined there.
"""
use Phoenix.Component
use Gettext, backend: MvWeb.Gettext
alias Phoenix.LiveView.JS
@doc """
Renders flash notices.
## Examples
<.flash kind={:info} flash={@flash} />
<.flash kind={:info} phx-mounted={show("#flash")}>Welcome Back!
"""
attr :id, :string, doc: "the optional id of flash container"
attr :flash, :map, default: %{}, doc: "the map of flash messages to display"
attr :title, :string, default: nil
attr :kind, :atom,
values: [:info, :error, :success, :warning],
doc: "used for styling and flash lookup"
attr :rest, :global, doc: "the arbitrary HTML attributes to add to the flash container"
slot :inner_block, doc: "the optional inner block that renders the flash message"
def flash(assigns) do
assigns = assign_new(assigns, :id, fn -> "flash-#{assigns.kind}" end)
~H"""
"""
end
@doc """
Renders a dropdown menu.
## Examples
<.dropdown_menu items={@items} open={@open} phx_target={@myself} />
When using custom content (e.g., forms), use the inner_block slot:
<.dropdown_menu button_label="Export" icon="hero-arrow-down-tray" open={@open} phx_target={@myself}>
"""
attr :id, :string, default: "dropdown-menu"
attr :items, :list, default: [], doc: "List of %{label: string, value: any} maps"
attr :button_label, :string, default: "Dropdown"
attr :icon, :string, default: nil
attr :checkboxes, :boolean, default: false
attr :selected, :map, default: %{}
attr :open, :boolean, default: false, doc: "Whether the dropdown is open"
attr :show_select_buttons, :boolean, default: false, doc: "Show select all/none buttons"
attr :phx_target, :any, required: true, doc: "The LiveView/LiveComponent target for events"
attr :menu_class, :string, default: nil, doc: "Additional CSS classes for the menu"
attr :menu_width, :string, default: "w-64", doc: "Width class for the menu (default: w-64)"
attr :button_class, :string,
default: nil,
doc: "Additional CSS classes for the button (e.g., btn-secondary)"
attr :menu_align, :string,
default: "right",
doc: "Menu alignment: 'left' or 'right' (default: right)"
attr :testid, :string, default: "dropdown-menu", doc: "data-testid for the dropdown container"
attr :button_testid, :string, default: "dropdown-button", doc: "data-testid for the button"
attr :menu_testid, :string,
default: nil,
doc: "data-testid for the menu (defaults to testid + '-menu')"
slot :inner_block, doc: "Custom content for the dropdown menu (e.g., forms)"
def dropdown_menu(assigns) do
menu_testid = assigns.menu_testid || "#{assigns.testid}-menu"
assigns = assign(assigns, :menu_testid, menu_testid)
~H"""
<%= if assigns.inner_block != [] do %>
{render_slot(@inner_block)}
<% else %>
{gettext("Options")}
<%= for item <- @items do %>
<% end %>
<% end %>
"""
end
@doc """
Renders a section in with a border similar to cards.
## Examples
<.form_section title={gettext("Personal Data")}>
"""
end
@doc """
Renders an input with label and error messages.
A `Phoenix.HTML.FormField` may be passed as argument,
which is used to retrieve the input name, id, and values.
Otherwise all attributes may be passed explicitly.
## Types
This function accepts all HTML input types, considering that:
* You may also set `type="select"` to render a `