Textarea

Multi-line text field with sizes and content-aware auto-grow.

Basic

.heex
<.textarea name="comments" placeholder="Add a comment..." />

Label, sublabel, description, help text

label, sublabel, description, and help_text render the field's labelling without extra wrappers.

(required)

Summarize what changed in this release for end users.

Aim for 3-5 short bullet points.
.heex
<.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={5}
  placeholder="What's new..."
/>

Sizes

Set size to one of sm, md, lg, or xl to match the surrounding density.

.heex
<.textarea size="sm" name="size_sm" placeholder="Small" />
<.textarea size="md" name="size_md" placeholder="Medium (default)" />
<.textarea size="lg" name="size_lg" placeholder="Large" />
<.textarea size="xl" name="size_xl" placeholder="Extra large" />

Initial height

Set rows to control the initial visible line count. The native resize handle still works.

.heex
<.textarea name="bio" label="Biography" rows={6} placeholder="Tell us about yourself..." />

Auto-grow

Add autogrow with min_rows and max_rows so the field expands and shrinks with its contents. Pure CSS, no JavaScript or layout shift.

.heex
<.textarea
  name="autogrow_message"
  label="Message"
  autogrow
  min_rows={2}
  max_rows={8}
  placeholder="Type to see the field grow..."
/>

Chat composer

Start at one row and expand up to ten with autogrow, then forward Enter to a LiveView event with phx-keydown and phx-key.

.heex
<.textarea
  name="message"
  autogrow
  min_rows={1}
  max_rows={10}
  placeholder="Send a message..."
  phx-keydown="maybe_send"
  phx-key="Enter"
/>

Disabled

.heex
<.textarea name="locked" label="Notes" value="This field cannot be edited." disabled />

Required field

Pair the native required attribute with a sublabel hint so the requirement is visible in the label.

(required)
.heex
<.textarea
  name="summary"
  label="Summary"
  sublabel="(required)"
  placeholder="One or two sentences..."
  required
/>

Character limit

maxlength caps input at the browser level; help_text surfaces the cap in the field.

280 characters max.
.heex
<.textarea
  name="tweet"
  label="Post"
  maxlength="280"
  help_text="280 characters max."
  rows={4}
  placeholder="What's happening?"
/>

Errors

Pass an errors list to render the field in the danger color with messages below. When bound to a field, errors flow from the changeset automatically.

.heex
<.textarea
  name="description"
  label="Description"
  value="too short"
  errors={["Description must be at least 10 characters."]}
/>

Form integration

Bind to a Phoenix.HTML.FormField with field={f[:name]}. The component derives id, name, value, and errors from the struct.

.heex
<.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" class="mt-3">Post comment</.button>
</.form>

Constrained width

By default the field fills its container. To narrow only the field while keeping the label area at its natural width, target [data-part=field-root] on any ancestor.

Goes to the product team. Anonymous unless you sign in.

.heex
<div class="**:data-[part=field-root]:max-w-xs">
  <.textarea
    name="feedback"
    label="How can we improve?"
    description="Goes to the product team. Anonymous unless you sign in."
    autogrow
    min_rows={3}
    max_rows={8}
  />
</div>