Skip to content
UI

Textarea

A multi-line text field for free-form input such as notes, comments and justifications.

@zenoxai/ui/components/textarea Markdown
<Field className="max-w-sm">
  <FieldLabel htmlFor="incident-notes">Incident notes</FieldLabel>
  <Textarea
    id="incident-notes"
    placeholder="What did you observe, and when?"
  />
</Field>

Usage

import { Field, FieldLabel } from "@zenoxai/ui/components/field"
import { Textarea } from "@zenoxai/ui/components/textarea"

export function IncidentNotes() {
  return (
    <Field>
      <FieldLabel htmlFor="incident-notes">Incident notes</FieldLabel>
      <Textarea id="incident-notes" placeholder="What did you observe?" />
    </Field>
  )
}

Use a textarea when the answer can run past one line: incident notes, a suppression reason, a comment. For a single line (a name, a domain, a search query), use an Input. To attach buttons or addons inside the field’s border, use InputGroupTextarea from Input Group.

Textarea is a styled native <textarea> and accepts all its attributes. It grows with its content from a 64px minimum (CSS field-sizing: content, in the browsers that support it). Set a max-h-* class to cap the height; past it, the field scrolls. Where the field grows on its own, the native resize grip is hidden; in browsers without field-sizing it stays, as the only way to make the field taller.

Examples

With a description

Add a FieldDescription under the field for guidance the user needs before typing, and point aria-describedby at it.

Shown in the audit log next to your name.

<Field className="max-w-sm">
  <FieldLabel htmlFor="suppression-reason">Suppression reason</FieldLabel>
  <Textarea
    id="suppression-reason"
    aria-describedby="suppression-reason-description"
    placeholder="Why should this alert stop firing?"
  />
  <FieldDescription id="suppression-reason-description">
    Shown in the audit log next to your name.
  </FieldDescription>
</Field>

Invalid

Set aria-invalid to draw the error border, and show the message in a FieldError linked with aria-describedby. Say what to fix, not only what is wrong.

<Field className="max-w-sm">
  <FieldLabel htmlFor="takedown-justification">
    Takedown justification
  </FieldLabel>
  <Textarea
    id="takedown-justification"
    aria-invalid
    aria-describedby="takedown-justification-error"
    defaultValue="Phishing"
  />
  <FieldError id="takedown-justification-error">
    Describe the evidence in at least 20 characters.
  </FieldError>
</Field>

Disabled

A disabled textarea is not focusable and is not submitted with the form. For text the user must still be able to select and copy, use readOnly instead.

<Field className="max-w-sm">
  <FieldLabel htmlFor="closing-summary">Closing summary</FieldLabel>
  <Textarea
    id="closing-summary"
    disabled
    defaultValue="False positive: the domain belongs to a partner and was added to the allow list."
  />
</Field>

With a button

A comment box: the textarea and its submit button in a form. Use aria-label when the layout has no room for a visible label and the purpose is clear from context.

<form
  className="flex w-full max-w-sm flex-col items-end gap-2"
  onSubmit={(event) => event.preventDefault()}
>
  <Textarea aria-label="Comment" placeholder="Add a comment for the team" />
  <Button type="submit" size="sm">
    Add comment
  </Button>
</form>

Accessibility

  • Every textarea needs a label: a FieldLabel (or Label) with htmlFor, or aria-label. A placeholder is not a label; it disappears as soon as the user types.
  • Field does not connect descriptions and errors to the control. Give them an id and list it in the textarea’s aria-describedby.
  • The font is 16px below the md breakpoint so iOS Safari does not zoom in on focus.

API reference

Generated from the TypeScript source. className, style and children are accepted everywhere and omitted below.

Textarea

Textarea is a multi-line text field that grows with its content, for comments and descriptions. For a single line use Input; to attach buttons or a counter, an InputGroup with InputGroupTextarea.

No props of its own. Accepts the props of the element it renders.