Gecko UIGecko UI

RHFTextarea

Multi-line text input component integrated with React Hook Form

You are reading the v1 docs. v2 renamed several props and replaced GeckoUIPortal with GeckoUIProvider. Read this page in v2.

Live examples are only rendered in the v2 docs.

RHFTextarea

A multi-line textarea component integrated with React Hook Form that automatically displays error states with a red border when validation fails. Supports auto-resizing functionality.

Installation

import { RHFTextarea } from '@geckoui/geckoui';

Basic Usage

import { useForm, FormProvider } from 'react-hook-form';
import { RHFTextarea } from '@geckoui/geckoui';

function Example() {
  const methods = useForm({
    defaultValues: {
      description: ''
    }
  });

  return (
    <FormProvider {...methods}>
      <RHFTextarea name="description" placeholder="Enter description" />
    </FormProvider>
  );
}

Props API

Extends all props from Textarea component plus:

PropTypeDefaultDescription
namestring-Field name (required)
controlControlAuto-injectedOptional: Pass explicitly for nested forms or custom form context
rulesRegisterOptions-Inline validation rules
autoResizebooleanfalseEnable automatic height adjustment
rowsnumber2Minimum number of rows
maxRowsnumber-Maximum number of rows (only with autoResize)
onChange(value: string) => void-Change callback (receives value, not event)
onBlur(value: string) => void-Blur callback
...restTextareaProps-All Textarea component props

Examples

With Validation (Zod)

import { useForm, FormProvider } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
import { RHFTextarea, RHFInputGroup } from '@geckoui/geckoui';

const schema = z.object({
  bio: z.string().min(10, 'Bio must be at least 10 characters').max(500, 'Bio must not exceed 500 characters')
});

function Example() {
  const methods = useForm({
    resolver: zodResolver(schema),
    mode: 'onBlur',
    defaultValues: { bio: '' }
  });

  return (
    <FormProvider {...methods}>
      <RHFInputGroup label="Bio" required>
        <RHFTextarea name="bio" placeholder="Tell us about yourself (min 10 chars)" />
      </RHFInputGroup>
    </FormProvider>
  );
}

Auto-Resizing Textarea

<RHFTextarea
  name="comments"
  autoResize
  rows={3}
  maxRows={10}
  placeholder="This textarea grows as you type (max 10 rows)"
/>

With Row Constraints

<RHFTextarea
  name="notes"
  rows={5}
  placeholder="Fixed at 5 rows"
/>

Disabled State

<RHFTextarea name="readonly" disabled />

Complete Form Example

import { useForm, FormProvider } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
import { RHFTextarea, RHFInputGroup, Button } from '@geckoui/geckoui';

const schema = z.object({
  title: z.string().min(1, 'Title is required'),
  description: z.string().min(20, 'Description must be at least 20 characters'),
  notes: z.string().optional()
});

function FormExample() {
  const methods = useForm({
    resolver: zodResolver(schema),
    mode: 'onBlur',
    defaultValues: {
      title: '',
      description: '',
      notes: ''
    }
  });

  return (
    <FormProvider {...methods}>
      <form onSubmit={methods.handleSubmit(console.log)}>
        <RHFInputGroup label="Title" required>
          <RHFTextarea name="title" rows={1} placeholder="Enter title" />
        </RHFInputGroup>

        <RHFInputGroup label="Description" required>
          <RHFTextarea
            name="description"
            autoResize
            rows={3}
            maxRows={8}
            placeholder="Enter description (min 20 chars)"
          />
        </RHFInputGroup>

        <RHFInputGroup label="Additional Notes">
          <RHFTextarea name="notes" rows={2} placeholder="Optional notes" />
        </RHFInputGroup>

        <Button type="submit">Submit</Button>
      </form>
    </FormProvider>
  );
}

Inline Rules Validation

For simple validation, use the rules prop:

<RHFTextarea
  name="description"
  rules={{
    required: 'Description is required',
    minLength: { value: 10, message: 'Must be at least 10 characters' }
  }}
/>

For complex forms, we recommend using a schema resolver (Zod, Yup) instead.

Error States

RHFTextarea automatically displays error states with:

  • Red border via data-error attribute on the root element when fieldState.error exists
.GeckoUIRHFTextarea[data-error] {
  border-color: red;
}

Use RHFInputGroup component for label + textarea + error layout:

<RHFInputGroup label="Description" required>
  <RHFTextarea name="description" />
</RHFInputGroup>

Or combine with RHFError component manually:

<RHFTextarea name="description" />
<RHFError name="description" />

Tip: Use mode: 'onBlur' in useForm to validate on blur for better UX:

const methods = useForm({
  resolver: zodResolver(schema),
  mode: 'onBlur'
});

Auto-Resize Behavior

When autoResize is enabled:

  • Textarea grows automatically as content increases
  • Minimum height is determined by the rows prop
  • Maximum height is determined by the maxRows prop
  • Shrinks back down when content is removed

When autoResize is disabled:

  • Textarea has a fixed height based on rows
  • Users can resize manually (if CSS allows)
  • The maxRows prop is ignored

Accessibility

  • Inherits all accessibility features from Textarea component
  • Proper ARIA attributes for error states
  • Keyboard navigable
  • Screen reader compatible