SutraUI.Input (Sutra UI v0.3.0)
View SourceRenders form input elements with label, description, and error handling.
The unified form field component for Sutra UI. This is a drop-in replacement
for Phoenix's generated input component, providing full parity with Phoenix
generators while using Sutra UI styling.
Basic Usage
# Simple text input
<.input type="text" name="username" placeholder="Username" />
# With label
<.input type="email" name="email" label="Email" placeholder="you@example.com" />
# With label and description
<.input
type="text"
name="username"
label="Username"
description="This will be your public display name."
placeholder="johndoe"
/>Phoenix Form Integration
Pass a Phoenix.HTML.FormField via the field attribute to automatically
extract the input's id, name, value, and validation errors:
<.simple_form for={@form} phx-submit="save">
<.input field={@form[:email]} type="email" label="Email" />
<.input field={@form[:password]} type="password" label="Password" />
<.input
field={@form[:bio]}
type="textarea"
label="Bio"
description="Tell us about yourself."
/>
<:actions>
<.button type="submit">Save</.button>
</:actions>
</.simple_form>Errors are displayed automatically when the field has been interacted with
(via Phoenix.Component.used_input?/1), so errors won't flash on first render.
Error Handling
Errors can come from two sources:
Automatic - from a
Phoenix.HTML.FormField(Ecto changeset errors):<.input field={@form[:email]} type="email" label="Email" />Manual - via the
errorsattribute:<.input name="email" errors={["can't be blank"]} />
When errors are present, the input gets aria-invalid="true" and error
messages render below the input with a destructive icon.
Input Types
This component handles all standard HTML input types, with special handling for:
type="checkbox"- Delegates toSutraUI.Checkboxwith hidden false valuetype="switch"- Delegates toSutraUI.Switch(toggle with role="switch")type="select"- Renders a native<select>elementtype="textarea"- Delegates toSutraUI.Textareatype="range"- Delegates toSutraUI.Sliderwith colocated hooktype="hidden"- Renders just the input, no wrapper or label
Type Examples
# Select with options
<.input
type="select"
name="country"
label="Country"
prompt="Select a country"
options={[{"United States", "us"}, {"Canada", "ca"}]}
/>
# Checkbox
<.input type="checkbox" name="terms" label="I agree to the terms" />
# Switch (toggle)
<.input type="switch" name="notifications" label="Enable notifications" />
# Textarea
<.input type="textarea" name="bio" label="Bio" rows={4} />
# Range slider
<.input type="range" name="volume" label="Volume" min={0} max={100} />Select Types
This component provides two ways to render select inputs:
Native Select (via <.input type="select">)
For standard form selects that work with Phoenix generators:
<.input
field={@form[:country]}
type="select"
label="Country"
prompt="Select a country"
options={[{"United States", "us"}, {"Canada", "ca"}]}
/>Custom Select (via SutraUI.Select)
For advanced features like search/filter, keyboard navigation, and custom styling,
use the dedicated SutraUI.Select component directly:
<.select id="country" name="country" value={@country} searchable>
<.select_option value="us" label="United States" />
<.select_option value="ca" label="Canada" />
</.select>See SutraUI.Select for more details.
Complete Form Example
Here is a realistic registration form demonstrating labels, descriptions, error handling, and multiple input types working together:
defmodule MyAppWeb.RegistrationLive do
use MyAppWeb, :live_view
def mount(_params, _session, socket) do
changeset = Accounts.change_user(%User{})
{:ok, assign(socket, form: to_form(changeset))}
end
def handle_event("validate", %{"user" => params}, socket) do
changeset =
%User{}
|> Accounts.change_user(params)
|> Map.put(:action, :validate)
{:noreply, assign(socket, form: to_form(changeset))}
end
def handle_event("save", %{"user" => params}, socket) do
case Accounts.create_user(params) do
{:ok, _user} -> {:noreply, push_navigate(socket, to: ~p"/dashboard")}
{:error, changeset} -> {:noreply, assign(socket, form: to_form(changeset))}
end
end
def render(assigns) do
~H"""
<.simple_form for={@form} phx-change="validate" phx-submit="save">
<.input
field={@form[:name]}
label="Full Name"
placeholder="Jane Smith"
/>
<.input
field={@form[:email]}
type="email"
label="Email"
description="We'll send a confirmation link to this address."
placeholder="jane@example.com"
/>
<.input
field={@form[:password]}
type="password"
label="Password"
description="Must be at least 8 characters."
placeholder="Create a password"
/>
<.input
field={@form[:role]}
type="select"
label="Role"
prompt="Choose a role"
options={[{"Developer", "dev"}, {"Designer", "design"}, {"Manager", "pm"}]}
/>
<.input
field={@form[:bio]}
type="textarea"
label="Bio"
description="Brief description for your profile."
rows={3}
/>
<.input
field={@form[:terms]}
type="checkbox"
label="I agree to the terms of service"
/>
<.input
field={@form[:newsletter]}
type="switch"
label="Subscribe to newsletter"
description="Receive weekly updates about new features."
/>
<:actions>
<.button type="submit">Create Account</.button>
</:actions>
</.simple_form>
"""
end
endAccessibility
- Labels are properly associated with inputs via wrapping
<label>elements - Description text is linked via
aria-describedbyon the input aria-invalidis automatically set when errors are present- Error messages are displayed below inputs with destructive styling
- Switch inputs include
role="switch"andaria-checked - Range inputs include
aria-valuemin,aria-valuemax,aria-valuenow - Supports standard ARIA attributes via
:rest
Summary
Functions
Renders an input with label, description, and error messages.
Translates an error message using gettext.
Translates the errors for a field from a keyword list of errors.
Functions
Renders an input with label, description, 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.
Examples
<.input field={@form[:email]} type="email" label="Email" />
<.input name="my-input" errors={["oh no!"]} />
<.input field={@form[:username]} label="Username" description="Pick something unique." />Attributes
id(:any) - The id attribute for the input. Defaults tonil.name(:any) - The name attribute for the input. Defaults tonil.label(:string) - Label text - renders label before input. Defaults tonil.description(:string) - Helper text rendered below the label, above the input. Defaults tonil.value(:any) - The value of the input. Defaults tonil.type(:string) - Defaults to"text". Must be one of"checkbox","color","date","datetime-local","email","file","hidden","month","number","password","range","search","select","switch","tel","text","textarea","time","url", or"week".field(Phoenix.HTML.FormField) - A form field struct retrieved from the form, for example: @form[:email].errors(:list) - List of error messages to display. Defaults to[].checked(:boolean) - The checked flag for checkbox inputs.prompt(:string) - The prompt for select inputs. Defaults tonil.options(:list) - The options to pass to Phoenix.HTML.Form.options_for_select/2.multiple(:boolean) - The multiple flag for select inputs. Defaults tofalse.class(:any) - Additional CSS classes. Defaults tonil.- Global attributes are accepted. Supports all globals plus:
["accept", "autocomplete", "capture", "cols", "disabled", "form", "list", "max", "maxlength", "min", "minlength", "multiple", "pattern", "placeholder", "readonly", "required", "rows", "size", "step", "phx-debounce", "phx-mounted", "aria-label", "aria-describedby", "aria-invalid", "aria-required"].
Translates an error message using gettext.
Translates the errors for a field from a keyword list of errors.