Packages
mbta_metro
0.0.9
1.1.2
1.1.1
1.1.0
1.0.1
1.0.0
0.3.3
0.3.2
0.3.1
0.3.0
0.2.4
0.2.3
0.2.2
0.2.1
0.2.0
0.1.21
0.1.20
0.1.19
0.1.18
0.1.17
0.1.16
0.1.15
0.1.14
0.1.13
0.1.12
0.1.11
0.1.10
0.1.9
0.1.8
0.1.7
0.1.6
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0
0.0.65
0.0.64
0.0.62
0.0.61
0.0.60
0.0.58
0.0.57
0.0.56
0.0.55
0.0.54
0.0.53
0.0.52
0.0.51
0.0.50
0.0.49
0.0.48
0.0.47
0.0.46
0.0.45
0.0.44
0.0.43
0.0.42
0.0.41
0.0.40
0.0.39
0.0.34
0.0.30
0.0.27
0.0.20
0.0.19
0.0.18
0.0.17
0.0.16
0.0.15
0.0.14
0.0.13
0.0.12
0.0.11
0.0.10
0.0.9
0.0.8
0.0.7
0.0.6
0.0.5
0.0.4
0.0.3
0.0.2
0.0.1
0.0.1-alpha
A Phoenix LiveView component library
Current section
Files
Jump to
Current section
Files
lib/mbta_metro/components/input.ex
defmodule MbtaMetro.Components.Input do
@moduledoc false
use Phoenix.Component
import MbtaMetro.Components.Feedback
@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 `<select>` tag
* `type="checkbox"` is used exclusively to render boolean values
* For live file uploads, see `Phoenix.Component.live_file_input/1`
See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input
for more information. Unsupported types, such as hidden and radio,
are best written directly in your templates.
## Examples
<.input field={@form[:email]} type="email" />
<.input name="my-input" errors={["oh no!"]} />
"""
attr :id, :any, default: nil
attr :name, :any
attr :label, :string, default: nil
attr :value, :any
attr :type, :string,
default: "text",
values:
~w(checkbox color date datetime-local email file month number password
range search select tel text textarea time url week radio checkbox_group_item radio_group_item)
attr :field, Phoenix.HTML.FormField,
doc: "a form field struct retrieved from the form, for example: @form[:email]"
attr :errors, :list, default: []
attr :class, :string, default: ""
attr :checked, :boolean, doc: "the checked flag for checkbox inputs"
attr :prompt, :string, default: nil, doc: "the prompt for select inputs"
attr :options, :list, doc: "the options to pass to Phoenix.HTML.Form.options_for_select/2"
attr :multiple, :boolean, default: false, doc: "the multiple flag for select inputs"
attr :rest, :global,
include: ~w(accept autocomplete capture cols disabled form list max maxlength min minlength
multiple pattern placeholder readonly required rows size step)
def input(%{field: %Phoenix.HTML.FormField{} = field} = assigns) do
errors = if used_input?(field), do: field.errors, else: []
assigns
|> assign(field: nil, id: assigns.id || field.id)
|> assign(
:label,
assigns.label ||
Phoenix.Naming.humanize(assigns.value)
)
|> assign(:errors, errors)
|> assign_new(:name, fn -> if assigns.multiple, do: field.name <> "[]", else: field.name end)
|> assign_new(:value, fn -> field.value end)
|> input()
end
def input(%{type: "checkbox"} = assigns) do
assigns =
assigns
|> assign_new(:checked, fn ->
Phoenix.HTML.Form.normalize_value("checkbox", assigns[:value])
end)
~H"""
<div class="flex">
<input type="hidden" name={@name} value="false" disabled={@rest[:disabled]} />
<input
type="checkbox"
id={@id}
name={@name}
value="true"
checked={@checked}
class={[
"shrink-0 mt-1 mr-3 border-silver-400 rounded text-blue-600 focus:border-blue-300 checked:border-blue-500 disabled:opacity-50 disabled:pointer-events-none",
@class
]}
{@rest}
/>
<.label for={@id}><%= @label %></.label>
</div>
"""
end
def input(%{type: "radio"} = assigns) do
assigns = assigns |> assign_new(:checked, fn -> false end)
~H"""
<div class="flex">
<input
type="radio"
id={@id}
name={@name}
value={@value}
checked={@checked}
class={[
"shrink-0 mt-1 mr-3 border-silver-400 rounded-full text-blue-600 focus:border-blue-300 checked:border-blue-500 disabled:opacity-50 disabled:pointer-events-none",
@class
]}
{@rest}
/>
<.label for={@id}><%= @label %></.label>
</div>
"""
end
def input(%{type: "select"} = assigns) do
~H"""
<div>
<.label for={@id}><%= @label %></.label>
<select
id={@id}
name={@name}
class={[
"mt-2 block w-full rounded-md border border-silver-400 bg-white shadow-sm focus:border-blue-500 focus:ring-0 sm:text-sm",
@class
]}
multiple={@multiple}
{@rest}
>
<option :if={@prompt} value=""><%= @prompt %></option>
<%= Phoenix.HTML.Form.options_for_select(@options, @value) %>
</select>
<.feedback :for={msg <- @errors} kind={:error}><%= msg %></.feedback>
</div>
"""
end
def input(%{type: "textarea"} = assigns) do
~H"""
<div>
<.label for={@id}><%= @label %></.label>
<textarea
id={@id}
name={@name}
class={[
"mt-2 block w-full rounded text-silver-900 focus:ring-0 sm:text-sm sm:leading-6 min-h-[6rem]",
@errors == [] && "border-silver-400 focus:border-blue-500",
@errors != [] && "border-red-400 focus:border-red-500",
@class
]}
{@rest}
><%= Phoenix.HTML.Form.normalize_value("textarea", @value) %></textarea>
<.feedback :for={msg <- @errors} kind={:error}><%= msg %></.feedback>
</div>
"""
end
# All other inputs text, datetime-local, url, password, etc. are handled here...
def input(assigns) do
~H"""
<div>
<.label for={@id}><%= @label %></.label>
<input
type={@type}
name={@name}
id={@id}
value={Phoenix.HTML.Form.normalize_value(@type, @value)}
class={[
"mt-2 block w-full rounded text-silver-900 focus:ring-0 sm:text-sm sm:leading-6",
@errors == [] && "border-silver-400 focus:border-blue-500",
@errors != [] && "border-red-400 focus:border-red-500",
@class
]}
{@rest}
/>
<.feedback :for={msg <- @errors} kind={:error}><%= msg %></.feedback>
</div>
"""
end
@doc """
Renders a label.
"""
attr :class, :string, default: ""
attr :for, :string, default: nil
slot :inner_block, required: true
def label(assigns) do
~H"""
<label for={@for} class="block text-sm font-inter-semibold leading-6 text-silver-800">
<%= render_slot(@inner_block) %>
</label>
"""
end
end