Diwa Design System

Textarea

A multi-line text input for longer freeform content. Supports validation states, labels, descriptions, and resizing.

When to use

Use diwa-textarea for freeform multi-line text input — messages, comments, descriptions, or any other content where the user may need more than one line. For single-line string data, prefer diwa-input-text or one of its specialised variants.

Vanilla JS

<diwa-textarea
  id="message-input"
  label="Message"
  description="Describe your request in detail."
  placeholder="Enter your message here..."
  rows="4"
  required
></diwa-textarea>

<script>
  const textarea = document.getElementById('message-input');
  textarea.addEventListener('change', (e) => {
    console.log('Value:', e.detail);
  });
</script>

React

import { useState } from 'react';

function MessageForm() {
  const [value, setValue] = useState('');
  const [error, setError] = useState('');

  const validate = (val: string) => {
    setError(val.trim().length < 10 ? 'Message must be at least 10 characters.' : '');
    setValue(val);
  };

  return (
    <diwa-textarea
      label="Message"
      description="Describe your request in detail."
      placeholder="Enter your message here..."
      rows={4}
      value={value}
      state={error ? 'error' : 'none'}
      message={error}
      required
      onchange={(e: CustomEvent<string>) => validate(e.detail)}
    />
  );
}

Validation states

Set state to "error" or "success" and provide a message to surface inline feedback underneath the textarea. When a message is provided the description is automatically hidden to avoid duplicate helper text.

Resize behaviour

The resize prop controls whether and in which direction the user can resize the textarea:

  • "vertical" (default) — drag the bottom-right handle to increase height.
  • "none" — disable resizing entirely; use only in constrained layouts.
  • "both" — allow resizing in both axes.
  • "horizontal" — allow resizing width only (rare).

Rows and height

The rows prop sets the initial visible height (default 4). Start with 3–5 rows for most use cases and let the user grow the field as needed via resize. Avoid pre-setting a very large row count — it pushes down subsequent form fields before the user has typed anything.

Dense mode (compact)

Set compact to reduce spacing and font size. Use this inside dense data-entry forms or tooling UIs where vertical space is at a premium — not in standard customer-facing flows.

Dos and don'ts

Do

  • Always provide a visible label — do not rely on placeholder text alone.
  • Use state="error" with a message to communicate validation failures.
  • Set resize="vertical" (default) to let users adjust height as needed.
  • Use the description prop to give context about expected format or length.
  • Start with a sensible default row count (3–5) for the expected content length.

Don't

  • Don't use a textarea for single-line inputs — use diwa-input-text instead.
  • Don't set resize="none" unless the layout would break if the textarea grew.
  • Don't rely solely on placeholder text — it disappears once the user starts typing.
  • Don't pre-set an excessive row count; let users expand the field if they need more space.