Skip to content

Textarea (components/ui/textarea.tsx)

Overview

A customizable textarea component that provides multi-line text input with support for auto-resizing, character count, and validation features.

Features

  • Auto-resize capability
  • Character count
  • Validation support
  • Error state handling
  • Placeholder text
  • Disabled state
  • Focus management
  • Accessibility support
  • Custom styling
  • ARIA attributes

Dependencies

import * as React from 'react'
import { forwardRef } from 'react'
import { cva, type VariantProps } from 'class-variance-authority'
import { cn } from '@/lib/utils'

Props

interface TextareaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
  error?: boolean | string;
  autoResize?: boolean;
  maxLength?: number;
  showCount?: boolean;
  className?: string;
  value?: string;
  onChange?: (value: string) => void;
}

Implementation

State Management

const [value, setValue] = useState(defaultValue || '');
const [isFocused, setIsFocused] = useState(false);

useEffect(() => {
  if (autoResize) {
    adjustHeight();
  }
}, [value, autoResize]);

Methods

const handleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
  const newValue = event.target.value;
  setValue(newValue);
  onChange?.(newValue);
};

const handleFocus = () => setIsFocused(true);
const handleBlur = () => setIsFocused(false);

const adjustHeight = () => {
  if (textareaRef.current) {
    textareaRef.current.style.height = 'auto';
    textareaRef.current.style.height = `${textareaRef.current.scrollHeight}px`;
  }
};

Unique Functionality

  • Auto-resize handling
  • Character counting
  • Error state management
  • Focus control
  • Value management
  • ARIA attributes

HTML Structure

<div className="relative">
  <textarea
    ref={textareaRef}
    className={cn(
      "flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
      error && "border-destructive focus-visible:ring-destructive",
      className
    )}
    value={value}
    onChange={handleChange}
    onFocus={handleFocus}
    onBlur={handleBlur}
    maxLength={maxLength}
    {...props}
  />
  {showCount && maxLength && (
    <div className="absolute bottom-1.5 right-1.5 text-xs text-muted-foreground">
      {value.length}/{maxLength}
    </div>
  )}
  {error && typeof error === 'string' && (
    <p className="mt-1 text-xs text-destructive">{error}</p>
  )}
</div>

API Integration

No direct API integration required.

Components Used

No additional components used.

Notes

  • Supports auto-resizing functionality
  • Handles character count display
  • Manages error states
  • Provides focus management
  • Maintains accessibility features
  • Supports custom styling
  • Uses semantic HTML elements