Fluxon.Components.Textarea
(Fluxon v3.1.1)
Provides <.textarea>, a labeled multi-line text input bound to either a Phoenix form
field or a plain name/value pair.
The component renders a <textarea> element together with optional label, sublabel,
description, helper text, and error messages. It supports a fixed-row layout (the
default) and a content-aware autogrow mode that resizes the field as its value
changes, starting at min_rows and growing without bound unless max_rows caps it.
Input vs Textarea vs Autocomplete vs Select
Fluxon offers several form controls for text-shaped values. Pick the one that matches the kind of value the user enters:
| Component | Value Kind | Use Case |
|---|---|---|
<.input> | A single line of free-form text or number | Names, emails, passwords, search, dates |
<.textarea> | Multi-line free-form text | Comments, descriptions, message bodies |
<.autocomplete> | One value chosen from a typed search | Picking from a long list while filtering |
<.select> | One value chosen from a fixed list | Status, category, country picker |
Usage
Render a textarea by providing a name. A label is recommended so the field has
a visible association for the user:
<.textarea name="comments" label="Comments" placeholder="Your thoughts..." />Most fields combine a label with a placeholder, helper text, and an explicit row count:
<.textarea
name="bio"
label="Biography"
description="A short paragraph that appears on your public profile."
help_text="Markdown is supported."
rows={5}
placeholder="Tell us about yourself..."
/>Sizes
The size attribute scales vertical/horizontal padding and font size. The default
is "md":
<.textarea name="size_sm" size="sm" placeholder="Small" />
<.textarea name="size_md" size="md" placeholder="Medium (Default)" />
<.textarea name="size_lg" size="lg" placeholder="Large" />
<.textarea name="size_xl" size="xl" placeholder="Extra Large" />| Size | Text | Use Case |
|---|---|---|
sm | sm | Dense layouts: compact admin forms, side panels |
md | sm | Default for most forms |
lg | base | Prominent text fields: support contact forms |
xl | lg | High-emphasis surfaces, single-field publishing UIs |
Labels, Description, and Helper Text
The label area can carry up to three distinct strings:
label: the primary label rendered above the field.sublabel: short inline text rendered next to the label, typically a state hint such as"(required)"or"(optional)".description: longer guidance rendered between the label and the field.
Helper text rendered below the field uses the help_text attribute:
<.textarea
name="release_notes"
label="Release notes"
sublabel="(required)"
description="Summarize what changed in this release for end users."
help_text="Aim for 3-5 short bullet points."
rows={6}
/>Form Integration
The component supports two binding modes: a Phoenix.HTML.FormField struct via
field (changeset-driven forms) or a plain name (standalone fields).
Bind to a form field
When field is set, the component derives id, name, value, and errors from
the form field struct. Errors are translated and rendered automatically, but only
after the field has been touched (Phoenix.Component.used_input?/1):
<.form :let={f} for={@form} phx-change="validate" phx-submit="save">
<.textarea field={f[:description]} label="Description" rows={6} />
</.form>Standalone textarea
When you don't have a changeset, pass name, optionally value, and any error
list directly:
<.textarea name="note" placeholder="Add a note..." value={@note} />
<.textarea name="reason" errors={["Reason is required."]} />Picking the Binding Mode
Use field for changeset-backed forms (CRUD, validation, nested data). Use
name for one-off fields without a changeset (feedback widgets, ad-hoc
comment boxes, controls whose value is held in socket assigns).
States
Disabled
Disabled textareas cannot be focused or edited and render with reduced contrast.
Disabling a parent <fieldset> cascades to descendant fields through HTML's native
:disabled semantics:
<.textarea name="locked" value="Cannot change" disabled />
<fieldset disabled>
<.textarea name="bio" value="..." />
</fieldset>Errors
When the errors list is non-empty (or the bound form field has errors), the field
renders in the danger color and each message is shown below the textarea:
<.textarea
name="description"
value="too short"
errors={["Description must be at least 10 characters."]}
/>When using field, errors are pulled from field.errors and translated through
the configured Gettext backend.
Height and Resizing
By default, the field renders at a fixed rows height and the user can drag the
native browser resize handle in the bottom-right corner to make it taller. Pass an
explicit rows to set the initial height:
<.textarea name="comments" label="Comments" rows={6} />Auto-growing height
Pass autogrow to make the field expand and shrink with its contents. By
default the field grows without an upper bound; set max_rows to cap the
height, after which content scrolls within the field. The native resize handle
is disabled in this mode since the height is driven by content:
<.textarea
name="message"
label="Message"
autogrow
min_rows={2}
max_rows={8}
placeholder="Type your message..."
/>Autogrow reacts to typing instantly on the client, with no LiveView round-trip
or hook, and behaves consistently across every browser. The rows attribute is
ignored when autogrow is enabled; min_rows sets the starting height so the
field looks right before any value is entered. When max_rows is set, content
beyond that height scrolls inside the field instead of expanding it further,
with the scrollbar flush against the field's edge.
Constraining Field Width
By default, the field fills the width of its container. To narrow only the field
while keeping the label, description, and helper text at their natural width, apply
a width utility to any ancestor that targets [data-part=field-root]:
<div class="**:data-[part=field-root]:max-w-xs">
<.textarea label="Notes" description="Brief notes only." name="notes" />
</div>This pattern works uniformly across all Fluxon input-shaped form components.
Examples
Comment form bound to a changeset
<.form :let={f} for={@form} phx-change="validate" phx-submit="save">
<.textarea
field={f[:body]}
label="Comment"
placeholder="Share your thoughts..."
rows={4}
phx-debounce="blur"
/>
<.button type="submit" color="primary">Post comment</.button>
</.form>Chat composer that grows with the message
<.textarea
name="message"
label="Message"
autogrow
min_rows={1}
max_rows={10}
placeholder="Send a message..."
phx-keydown="maybe_send"
phx-key="Enter"
/>Required field with sublabel and description
<.textarea
field={@form[:summary]}
label="Summary"
sublabel="(required)"
description="Used as the preview text wherever this post is linked."
help_text="Keep it under 200 characters."
rows={3}
maxlength="200"
required
/>Constrained-width feedback widget
<div class="**:data-[part=field-root]:max-w-md">
<.textarea
name="feedback"
label="How can we improve?"
autogrow
min_rows={3}
max_rows={8}
/>
</div>
Summary
Components
Renders a labeled multi-line text input with support for sizes, autogrow, and form integration.
Components
Renders a labeled multi-line text input with support for sizes, autogrow, and form integration.
Use this for any free-form multi-line value: comments, descriptions, message
bodies, release notes, feedback. The component renders the <textarea> element
plus its surrounding label, description, helper text, and error messages.
Pass a Phoenix.HTML.FormField via field to bind the textarea to a changeset-backed
form, or pass name, value, and optionally errors directly for standalone use.
Attributes
id(:string) - Sets the textarea'sid. When omitted, the component falls back to the value ofname(or tofield.idwhenfieldis set) so the rendered<label>can target the textarea viafor.Defaults to
nil.field(Phoenix.HTML.FormField) - APhoenix.HTML.FormFieldstruct, typically obtained from a form binding such asf[:body]. When provided, the textarea derives itsid,name,value, anderrorsfrom the struct, and runs error messages through the project's translation helper. Errors are only shown after the field has been touched, as reported byPhoenix.Component.used_input?/1.class(:any) - Extra CSS classes applied to the underlying<textarea>element. Use this to adjust typography (for examplefont-mono), padding, or background without affecting the surrounding label and helper text.Defaults to
nil.help_text(:string) - Helper text rendered below the field. Use for tips, formatting hints, or follow-up instructions that are easier to read after the user has seen the textarea.Defaults to
nil.label(:string) - Primary label text rendered above the field. Associated with the textarea through theforattribute, using the textarea'sid. When omitted, no<label>is rendered.Defaults to
nil.sublabel(:string) - Short inline hint rendered alongside the mainlabel. Use for state cues such as"(required)"or"(optional)"that belong with the label rather than the field.Defaults to
nil.description(:string) - Longer guidance text rendered between the label and the field. Use for sentences that explain the field's purpose or set expectations about the value.Defaults to
nil.value(:string) - The current value of the textarea. Required when not usingfield. Whenfieldis set, this attribute is ignored in favor offield.value. Defaults to an empty string when neithervaluenorfieldprovides one.errors(:list) - A list of error message strings rendered below the field. Whenfieldis set, errors are pulled fromfield.errorsand translated automatically; use this attribute to surface errors on standalone fields that are not bound to a form field.Defaults to
[].name(:string) - The submitted name for the textarea. Required when not usingfield. Whenfieldis set, this attribute is ignored in favor offield.name.rows(:integer) - The number of visible text lines, mapped directly to the underlying<textarea rows>attribute. Ignored whenautogrowistrue, in which casemin_rowsis used as the fallbackrowsvalue for browsers withoutfield-sizingsupport.Defaults to
3.autogrow(:boolean) - Whentrue, the field expands and shrinks to fit its content, starting atmin_rowsand growing without bound unlessmax_rowscaps it. The native resize handle is disabled in this mode.Defaults to
false.min_rows(:integer) - Minimum number of visible rows whenautogrowis enabled. Also used as the underlying<textarea rows>value so the field has a sensible initial height before any value is rendered.Defaults to
2.max_rows(:integer) - Maximum number of visible rows whenautogrowis enabled. When set, content beyond this height scrolls within the field. When omitted (the default), the field grows without an upper bound and never scrolls.Defaults to
nil.disabled(:boolean) - Whentrue, the field cannot be focused or edited and renders with reduced contrast. Disabling a parent<fieldset>cascades through HTML's native:disabledsemantics without setting this attribute on each textarea.Defaults to
false.size(:string) - Controls the field's vertical/horizontal padding and font size.sm: Compact padding withsmtext. Best for dense layouts and side panels.md: Default padding withsmtext. Suitable for most forms.lg: Larger padding withbasetext. Good for prominent fields such as support contact forms.xl: Largest padding withlgtext. For high-emphasis surfaces and single-field publishing UIs.
Defaults to
"md".Defaults to
"md". Must be one of"sm","md","lg", or"xl".Global attributes are accepted. Any additional HTML attributes supported by
<textarea>, forwarded as-is to the rendered element. Common values includeplaceholder,maxlength,minlength,required,readonly,spellcheck, and Phoenix bindings such asphx-change,phx-debounce, andphx-blur. Supports all globals plus:["autocomplete", "cols", "dirname", "disabled", "form", "maxlength", "minlength", "name", "placeholder", "readonly", "required", "rows", "wrap", "spellcheck"].