'use client'
import { css, cx } from '@styled-system/css'
import { type TextareaVariantProps, textarea } from '@styled-system/recipes'
import type { SystemStyleObject } from '@styled-system/types'
import React from 'react'
const resizeClasses = {
none: css({ resize: 'none' }),
vertical: css({ resize: 'vertical' }),
horizontal: css({ resize: 'horizontal' }),
both: css({ resize: 'both' }),
} as const
export type TextareaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement> &
TextareaVariantProps & {
resize?: keyof typeof resizeClasses
css?: SystemStyleObject
}
export const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
({ className, variant, size, radii, resize = 'vertical', css: cssProp, ...props }, ref) => (
<textarea
ref={ref}
className={cx(textarea({ variant, size, radii }), resizeClasses[resize], cssProp && css(cssProp), className)}
{...props}
/>
),
)
Textarea.displayName = 'Textarea'import { Textarea } from '@/components/ui/textarea'
<Textarea placeholder="Type your message here." />Three sizes (sm, md, lg) to match the density of the surrounding form. The default is md.
Four visual styles — outline (default), underlined, filled, and borderless — matching the Input component's styling options. Choose based on your form's visual hierarchy.
Apply data-status="error", data-status="success", or data-status="warning" to show contextual feedback. Always pair the visual state with a helper text message — the color change alone is not sufficient for screen readers.
Adjust corner rounding with the radii prop (sm, md, lg) independently of the variant. Use lg or sm to match the rounding style of surrounding form controls.
Use disabled to prevent interaction when the field is not applicable in the current state. The textarea is visually dimmed to signal its unavailability.
Pair the Textarea with a Button to build a message input area. Wrap both in a flex container and position the button below or alongside the field.
Always associate a Label with the Textarea using matching htmlFor and id attributes. This is required for accessible field identification.
Add a supporting paragraph below the Textarea to provide instructions, character limits, or context about the expected input.
Your message will be copied to the support team.
Full form integration with controlled state, client-side validation, and inline error messaging.
| Prop | Type | Default | Description |
|---|---|---|---|
variant | 'outline' | 'underlined' | 'filled' | 'borderless' | 'outline' | Visual style of the textarea |
size | 'sm' | 'md' | 'lg' | 'md' | Controls text size and padding |
radii | 'sm' | 'md' | 'lg' | 'md' | Border radius of the textarea |
resize | 'none' | 'vertical' | 'horizontal' | 'both' | 'vertical' | Controls user resize behavior |
disabled | boolean | false | Disables the textarea |