Skip to main content

Overview

The Textarea component provides a multi-line text input with support for auto-growing, validation states, labels, and helper text.

Basic Usage

  • Code
  • Preview
import { useState } from "react";
import { Textarea } from '@peppermint-design/devreadykit';

export default function App() {
  const [value, setValue] = useState("");

  return (
    <div className="w-full max-w-xl space-y-4">
      <Textarea
        value={value}
        onValueChange={setValue}
        label="Message"
        placeholder="Hi! I’d like to know more about…"
        helperText="Be as specific as you can"
      />
    </div>
  );
}

Auto Growing

Enable automatic height adjustment based on content.
  • Code
  • Preview
import { Textarea } from '@peppermint-design/devreadykit';

export default function AutoGrowExample() {
  return (
    <Textarea 
      label="Auto-growing textarea"
      placeholder="Type here and watch it grow..."
      autoGrow
      minRows={2}
    />
  );
}

Validation States

Error State

  • Code
  • Preview
import { Textarea } from '@peppermint-design/devreadykit';

export default function ErrorExample() {
  return (
    <Textarea 
      label="Message"
      placeholder="Enter your message..."
      errorMessage="Message is required and must be at least 10 characters"
      value="Short"
    />
  );
}

Disabled State

  • Code
  • Preview
import { Textarea } from '@peppermint-design/devreadykit';

export default function DisabledExample() {
  return (
    <Textarea 
      label="Disabled textarea"
      placeholder="Cannot edit this"
      disabled
      value="This is disabled"
    />
  );
}

Read Only State

  • Code
  • Preview
import { Textarea } from '@peppermint-design/devreadykit';

export default function ReadOnlyExample() {
  return (
    <Textarea 
      label="Read only textarea"
      placeholder="Cannot edit this"
      readOnly
      value="This is read only"
    />
  );
}

With Action Button

  • Code
  • Preview
import { Button, Textarea } from '@peppermint-design/devreadykit';

export default function ActionButtonExample() {
  return (
    <Textarea 
      label="Comment"
      placeholder="Write a comment..."
      action={
        <Button size="s" variant="plain">
          Post
        </Button>
      }
    />
  );
}

Props

PropTypeDefaultDescription
valuestringTextarea value
onValueChange(value: string, event: ChangeEvent) => voidChange handler
labelReact.ReactNodeLabel content
helperTextReact.ReactNodeHelper text
errorMessageReact.ReactNodeError message
actionReact.ReactNodeAction button
autoGrowbooleanfalseAuto-grow height
minRowsnumber3Minimum rows
requiredbooleanfalseRequired field
disabledbooleanfalseDisabled state
readOnlybooleanfalseRead only state
classNamestringAdditional CSS classes

Examples

Contact Form

  • Code
  • Preview
import { useState, type FormEvent } from "react";
import { Button, Textarea } from '@peppermint-design/devreadykit';

export default function ContactForm() {
  const [message, setMessage] = useState("");
  const [error, setError] = useState("");

  const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    if (message.trim().length < 10) {
      setError("Message must be at least 10 characters long");
      return;
    }
    setError("");
    // Submit form
  };

  return (
    <form onSubmit={handleSubmit}>
      <Textarea
        value={message}
        onValueChange={(value) => {
          setMessage(value);
          if (error && value.trim().length >= 10) {
            setError("");
          }
        }}
        label="Your Message"
        placeholder="Tell us how we can help..."
        helperText="Please provide as much detail as possible"
        errorMessage={error}
        autoGrow
        minRows={4}
        required
      />
      
      <Button type="submit" variant="filled" className="mt-4">
        Send Message
      </Button>
    </form>
  );
}

Comment System

  • Code
  • Preview
import { useState } from "react";
import { Button, Textarea } from '@peppermint-design/devreadykit';

export default function CommentInput() {
  const [comment, setComment] = useState("");
  const [comments, setComments] = useState<string[]>([]);

  const handlePost = () => {
    if (!comment.trim()) return;
    setComments((prev) => [comment.trim(), ...prev]);
    setComment("");
  };

  return (
    <div className="space-y-4">
      <Textarea
        value={comment}
        onValueChange={setComment}
        placeholder="Write a comment..."
        autoGrow
        minRows={2}
        action={
          <Button 
            size="s" 
            variant="filled"
            disabled={!comment.trim()}
            onClick={handlePost}
          >
            Post
          </Button>
        }
      />
      <div className="space-y-2">
        {comments.map((entry, index) => (
          <div key={`${entry}-${index}`} className="p-2 border rounded">
            {entry}
          </div>
        ))}
      </div>
    </div>
  );
}

Feedback Form

  • Code
  • Preview
import { useState } from "react";
import { Textarea } from '@peppermint-design/devreadykit';

const MAX_LENGTH = 500;

export default function FeedbackForm() {
  const [feedback, setFeedback] = useState("");
  const remaining = MAX_LENGTH - feedback.length;
  const isNearLimit = remaining <= 50;

  return (
    <div>
      <Textarea
        value={feedback}
        onValueChange={setFeedback}
        label="Feedback"
        placeholder="Share your thoughts..."
        helperText={`${feedback.length}/${MAX_LENGTH} characters`}
        autoGrow
        minRows={3}
        maxLength={MAX_LENGTH}
      />
      
      <div className="mt-2 text-sm text-gray-600 font-mono">
        {isNearLimit && (
          <span className="text-orange-600 font-mono">
            {remaining} characters remaining
          </span>
        )}
      </div>
    </div>
  );
}
I