Default

Auto-growing textarea with placeholder.

<textarea class="textarea" placeholder="Type your message..."></textarea>

Disabled

Non-interactive textarea.

<textarea class="textarea" disabled></textarea>

With description

Textarea with label and helper text.

You can use markdown in your bio.

<label class="label" for="bio">Bio</label>
<textarea class="textarea" id="bio" placeholder="Tell us..."></textarea>
<p class="field-description">You can use markdown.</p>

CSS view file

/* -- Textarea component ----------------------------------------- */

@layer components {
  .textarea {
    width: 100%;
    min-height: 5rem;
    border: 1px solid var(--input);
    border-radius: var(--radius-md);
    background: var(--background);
    padding: 0.5rem 0.75rem;
    font-size: 0.875rem;
    font-family: var(--font-sans);
    color: var(--foreground);
    outline: none;
    box-shadow: var(--shadow-xs);
    transition: border-color 150ms, box-shadow 150ms;
    resize: vertical;
    field-sizing: content;

    &:focus {
      border-color: var(--ring);
      box-shadow: 0 0 0 2px oklch(from var(--ring) l c h / 0.2);
    }

    &::placeholder { color: var(--muted-foreground); }

    &:disabled {
      opacity: 0.5;
      cursor: not-allowed;
      resize: none;
    }

    &:is([aria-invalid="true"], :user-invalid) {
      border-color: var(--destructive);

      &:focus {
        border-color: var(--destructive);
        box-shadow: 0 0 0 2px oklch(from var(--destructive) l c h / 0.2);
      }
    }
  }

  /* -- Accessibility ---------------------------------------- */
  @media (prefers-reduced-motion: reduce) {
    .textarea {
      transition: none;
    }
  }

  @media (prefers-contrast: more) {
    .textarea {
      border-width: 2px;
    }

    .textarea:disabled {
      opacity: 0.7;
    }
  }

  @media (forced-colors: active) {
    .textarea {
      border-color: ButtonBorder;
      color: ButtonText;
      background: Field;
    }

    .textarea:focus {
      outline: 2px solid Highlight;
      outline-offset: 1px;
    }

    .textarea:disabled {
      opacity: 1;
      color: GrayText;
      border-color: GrayText;
    }

    .textarea:is([aria-invalid="true"], :user-invalid) {
      border-color: LinkText;
    }
  }
}