Theme Switcher

TextArea

A multi-line plain-text editing control, useful when you want to allow users to enter a sizeable amount of free-form text, for example a comment on a review or feedback form.

import { TextArea } from "@ngrok/mantle/text-area";

<TextArea placeholder="Tell us about your experience…" />
<TextArea appearance="monospaced" placeholder="Tell us about your experience…" />
<TextArea placeholder="Tell us about your experience…" validation="error" />

Examples

TextArea in a form with client-side validation

In this example, the TextArea is used in a form with client-side validation. The form is built using @tanstack/react-formand zod for validation. The form accepts user feedback and validates the input before submission.

import { Button } from "@ngrok/mantle/button";
import { Label } from "@ngrok/mantle/label";
import { TextArea } from "@ngrok/mantle/text-area";
import { useForm } from "@tanstack/react-form";
import { z } from "zod";
import { useSubmit } from "react-router";

const formSchema = z.object({
	feedback: z.string().trim().min(1, "Please enter your feedback."),
});

type FormValues = z.infer<typeof formSchema>;

function FormExample() {
	const submit = useSubmit();
	const form = useForm({
		defaultValues: {
			feedback: "",
		} satisfies FormValues,
		validators: {
			onSubmit: formSchema,
		},
		onSubmit: ({ value }) => {
			// Handle form submission here
			submit(value, {
				method: "post",
			});
		},
	});

	return (
		<form
			className="space-y-4"
			onSubmit={(event) => {
				event.preventDefault();
				event.stopPropagation();
				void form.handleSubmit();
			}}
		>
			<div className="space-y-1">
				<Label htmlFor="feedback" className="block">
					Feedback:
				</Label>
				<form.Field name="feedback">
					{(field) => (
						<TextArea
							id={field.name}
							name={field.name}
							onBlur={field.handleBlur}
							onChange={(event) => field.handleChange(event.target.value)}
							placeholder="Tell us about your experience…"
							validation={field.state.meta.errors.length > 0 && "error"}
							value={field.state.value}
						/>
					)}
				</form.Field>
				<form.Field name="feedback">
					{(field) =>
						field.state.meta.errors.map((error) => (
							<p
								key={error?.message}
								className="text-sm leading-4 text-danger-600"
							>
								{error?.message}
							</p>
						))
					}
				</form.Field>
			</div>
			<form.Subscribe selector={(state) => state.isDirty}>
				{(isDirty) => (
					<Button type="submit" appearance="filled" disabled={!isDirty}>
						Submit
					</Button>
				)}
			</form.Subscribe>
		</form>
	);
}

API Reference

The TextArea accepts the following props in addition to the standard HTML textarea attributes.

PropTypeDefaultDescription
appearance
  • monospaced

Defines the visual style of the TextArea.

validation
  • error
  • success
  • warning
  • false
  • () => "error" | "success" | "warning" | false

Use the validation prop to show if the textarea has a specific validation status. This will change the border and outline of the textarea.

The false type is useful when using short-circuiting logic so that you don't need to use a ternary with undefined.

Setting validation to error also sets aria-invalid.