Textarea
Displays a form textarea or a component that looks like a textarea.
Basic Usage
import { Textarea } from "@repo/ui/components/textarea";
export function Example1() {
return (
<Textarea
placeholder="Type your message here."
className="w-80 sm:w-96"
/>
);
}
Disabled
import { Textarea } from "@repo/ui/components/textarea";
export function Example2() {
return (
<Textarea
isDisabled
placeholder="Type your message here."
className="w-80 sm:w-96"
/>
);
}
With Label
import { Label } from "@repo/ui/components/label";
import { Textarea } from "@repo/ui/components/textarea";
export function Example3() {
return (
<div className="grid w-full gap-1.5">
<Label htmlFor="message">Your message</Label>
<Textarea
placeholder="Type your message here."
id="message"
className="w-80 sm:w-96"
/>
</div>
);
}
With Text
Your message will be copied to the support team.
import { Label } from "@repo/ui/components/label";
import { Textarea } from "@repo/ui/components/textarea";
export function Example5() {
return (
<div className="grid w-full gap-1.5">
<Label htmlFor="message-2">Your Message</Label>
<Textarea
placeholder="Type your message here."
id="message-2"
className="w-80 sm:w-96"
/>
<p className="text-muted-foreground text-sm">
Your message will be copied to the support team.
</p>
</div>
);
}
With Button
import { Button } from "@repo/ui/components/button";
import { Textarea } from "@repo/ui/components/textarea";
export function Example4() {
return (
<div className="grid w-full gap-2">
<Textarea
placeholder="Type your message here."
className="w-80 sm:w-96"
/>
<Button>Send message</Button>
</div>
);
}
Component Code
"use client";
import { cn } from "@repo/ui/lib/utils";
import { ComponentProps, forwardRef, useRef } from "react";
import { AriaTextFieldOptions, useFocusRing, useTextField } from "react-aria";
import { mergeProps } from "@react-aria/utils";
type TextareaComponentProps = ComponentProps<"textarea">;
interface TextareaProps
extends TextareaComponentProps,
Omit<AriaTextFieldOptions<"textarea">, keyof TextareaComponentProps> {
className?: string;
}
export const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(
({ className = "", ...restProps }, ref) => {
const localRef = useRef<HTMLTextAreaElement>(null);
const mergedRef = (node: HTMLTextAreaElement | null) => {
if (!node) {
return;
}
localRef.current = node;
if (typeof ref == "function") {
ref(node);
} else if (ref) {
ref.current = node;
}
};
const { inputProps } = useTextField<"textarea">(
restProps as AriaTextFieldOptions<"textarea">,
localRef,
);
const { focusProps } = useFocusRing();
return (
<textarea
{...mergeProps(inputProps, focusProps)}
ref={mergedRef}
className={cn(
"placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input shadow-xs min-h-20 w-full min-w-0 rounded-md border bg-transparent px-3 py-2 text-base outline-none transition-[color,box-shadow] disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
"resize-y",
className,
)}
/>
);
},
);
Textarea.displayName = "Textarea";