Skip to content
VEXA
Forms

Textarea

Server-safe

A multi-line text field.

Live preview

Rendered from the installed VEXA source — the same files you receive.

Installation

Adds the component source to your project. Registry dependencies are pulled in automatically.

npx shadcn@latest add https://vexa.valfiguer.com/r/textarea.json

Installs to components/vexa/textarea.tsx

npm dependencies

No external npm dependencies.

Registry dependencies

  • @vexa/utils

Other VEXA items this component needs. Install them first — they are resolved automatically by the CLI.

Source

Copy this into its target path, or install it with the command above.

components/vexa/textarea.tsx
import type * as React from "react";

import { cn } from "@/lib/utils";

/**
 * Textarea — a multi-line text field.
 *
 * RSC-safe as static markup; add `onChange`/controlled state from a Client
 * Component. States covered: default, focus-visible, disabled, read-only, and
 * invalid (set `aria-invalid` — validity is not communicated by color alone,
 * the border and ring both change). Always pair with a `<Label htmlFor>`.
 */
export function Textarea({
  className,
  ...props
}: React.ComponentProps<"textarea">) {
  return (
    <textarea
      data-slot="textarea"
      className={cn(
        "flex min-h-20 w-full resize-y rounded-vexa-md border border-vexa-input bg-vexa-surface-raised px-3 py-2 text-sm text-vexa-foreground shadow-vexa-sm",
        "transition-[color,box-shadow,border-color] duration-[var(--vexa-duration-fast)]",
        "placeholder:text-vexa-muted-foreground",
        "outline-none focus-visible:border-vexa-focus focus-visible:ring-2 focus-visible:ring-vexa-ring focus-visible:ring-offset-1 focus-visible:ring-offset-vexa-background",
        "disabled:cursor-not-allowed disabled:opacity-60",
        "read-only:bg-vexa-muted read-only:text-vexa-muted-foreground",
        "aria-[invalid=true]:border-vexa-danger aria-[invalid=true]:focus-visible:ring-vexa-danger",
        className,
      )}
      {...props}
    />
  );
}

Details

Example

tsx
<Textarea id="bio" placeholder="Tell us about your team" />

Accessibility

Pair with <Label htmlFor>. Invalid state uses aria-invalid and changes border + ring (not color alone). Read-only and disabled states styled.