Meowland docs
Workbench

Component reference

Textarea

A multi-line text input.

Preview

Textarea has no story of its own; this one draws it as part of Input.

Read-only, errors and long content

Read-only content can still be selected and copied; disabled content cannot be edited. Explicit errors, composed fields and long content keep a clear association.

packages/meowtail/stories/input-states.stories.tsxline 21tsx
render: () => (
  <div className="workshop-composition-columns">
    <section className="workshop-stack">
      <Field
        label="Project path (read-only)"
        htmlFor="readonly-path"
        description="Can be selected and copied; it cannot be changed here."
      >
        <Input
          id="readonly-path"
          readonly
          value="/workspace/meowland/packages/meowtail/components/long-project-reference"
        />
      </Field>
      <Field label="Search files" htmlFor="search-files">
        <Input id="search-files" type="search" placeholder="Enter a file name…" />
      </Field>
      <Field
        label="Notification email"
        htmlFor="invalid-email"
        invalid
        error="Enter a complete email address."
      >
        <Input id="invalid-email" type="email" value="meow@" />
      </Field>
      <Field label="Access passphrase (disabled)" htmlFor="disabled-password">
        <Input id="disabled-password" type="password" value="demo-only" disabled />
      </Field>
      <Field
        label="Check range"
        description="For composed fields, the caller associates the label and description separately."
        descriptionId="range-description"
      >
        <div className="workshop-foundation-range">
          <label>
            From{" "}
            <Input
              aria-label="Start line"
              aria-describedby="range-description"
              type="number"
              value="1"
              min="1"
            />
          </label>
          <label>
            To{" "}
            <Input
              aria-label="End line"
              aria-describedby="range-description"
              type="number"
              value="80"
              min="1"
            />
          </label>
        </div>
      </Field>
    </section>
    <section className="workshop-stack">
      <Field label="Delivery notes (editable)" htmlFor="long-notes">
        <Textarea id="long-notes" rows={6}>
          First, confirm every component stays readable on narrow screens. Second, keep user input
          while switching themes. Third, open a dialog with the keyboard, cancel it and return.
          Long content should wrap naturally; never drop the evidence for checks to keep the
          screen tidy.
        </Textarea>
      </Field>
      <Field label="Last check record (read-only)" htmlFor="readonly-notes">
        <Textarea id="readonly-notes" rows={3} readonly>
          The record is kept for checking. Read-only does not mean inaccessible.
        </Textarea>
      </Field>
      <Field label="Waiting for the connection to return" htmlFor="disabled-notes">
        <Textarea id="disabled-notes" rows={3} disabled>
          Continue editing once the connection returns.
        </Textarea>
      </Field>
    </section>
  </div>
)

Installation

bun add meowtail

Usage

Taken from the examples on this page.

usage.tsxtsx
import { Textarea } from "meowtail";

<Textarea id="long-notes" rows={6}>
  First, confirm every component stays readable on narrow screens. Second, keep user input
  while switching themes. Third, open a dialog with the keyboard, cancel it and return.
  Long content should wrap naturally; never drop the evidence for checks to keep the
  screen tidy.
</Textarea>

Examples

Other stories that draw Textarea.

Normal and long labels

Native input behavior and Field label association; long labels, helper descriptions, and multi-line content are shown together.

packages/meowtail/stories/foundation.stories.tsxline 169tsx
render: () => {
  const delivery = signal("review");
  return (
    <form className="workshop-stack workshop-constrained" data-project-form novalidate>
      <Field
        label="Project name"
        htmlFor="workshop-project"
        description="Local demo only; nothing is saved to a service."
      >
        <Input id="workshop-project" name="project" value="Meowland" required />
      </Field>
      <Field
        label="Delivery method"
        htmlFor="workshop-delivery"
        description="Review the diff first, then decide whether to submit."
      >
        <Select
          id="workshop-delivery"
          name="delivery"
          aria-describedby="workshop-delivery-description"
          value={delivery}
          required
          onChange={(event) => {
            delivery.value = (event.currentTarget as HTMLSelectElement).value;
          }}
        >
          <option value="draft">Keep draft</option>
          <option value="review">Review the diff first</option>
          <option value="export">Export results</option>
        </Select>
        <div className="workshop-foundation-field-action">
          <span>Not sure which to pick?</span>
          <Button
            variant="quiet"
            size="small"
            onClick={() => {
              delivery.value = "review";
            }}
          >
            Use recommended settings
          </Button>
        </div>
      </Field>
      <Field
        label="Add constraints this work must follow and how you want the results checked when done"
        htmlFor="workshop-notes"
      >
        <Textarea
          id="workshop-notes"
          rows={4}
          placeholder="Write down constraints, or paste longer content…"
        />
      </Field>
      <div className="workshop-row">
        <Button type="submit">Save project</Button>
        <Button type="reset" variant="quiet">
          Restore initial values
        </Button>
      </div>
      <Note id="project-feedback" role="status">
        Change the name and save; leave it empty to see validation feedback.
      </Note>
    </form>
  );
}

Error and disabled

The error description is associated with the control by a real Field; a disabled input stays readable. This sample uses a fixed error state.

packages/meowtail/stories/foundation.stories.tsxline 278tsx
render: () => (
  <div className="workshop-stack workshop-constrained">
    <Field
      label="Project name"
      htmlFor="workshop-invalid"
      error="Enter a project name; spaces alone are not enough."
    >
      <Input id="workshop-invalid" value="" />
    </Field>
    <Field
      label="Working directory"
      htmlFor="workshop-disabled"
      description="The directory cannot be changed while running."
    >
      <Input id="workshop-disabled" value="/workspace/meowland" disabled />
    </Field>
    <Field
      label="Runtime environment"
      htmlFor="workshop-disabled-select"
      description="Cannot be switched while work is in progress."
    >
      <Select id="workshop-disabled-select" disabled>
        <option>Local workspace</option>
      </Select>
    </Field>
    <Field
      label="Additional notes"
      htmlFor="workshop-invalid-notes"
      error="The description exceeds the length allowed by this sample; shorten it and continue."
    >
      <Textarea id="workshop-invalid-notes" rows={3}>
        A longer description that needs to be added.
      </Textarea>
    </Field>
  </div>
)

API reference

Props

Also takes className, children and the attributes and events of its root element.

DOM parts

root

Registry

The component is registered as textarea in the meowtail component registry.