Skip to main content

Text Area

Text Area is a form control that lets people enter several lines of text, such as a project description or feedback.

Import

import { TextArea } from '@vortexlabs/vortex';
import type { TextAreaProps } from '@vortexlabs/vortex';

Allied components

Other links

Summarize the goal in a few sentences.
<Stack
  width="440px"
  maxWidth="100%"
>
  <TextArea.Root
    size="md"
    variant="outline"
  >
    <TextArea.Label>Project description</TextArea.Label>
  <TextArea.Input name="playground-description" placeholder="What will this project achieve?" />
  <TextArea.HelperText>Summarize the goal in a few sentences.</TextArea.HelperText>
  <TextArea.ErrorMessage>Add a project description.</TextArea.ErrorMessage>
  </TextArea.Root>
</Stack>

Features

  • Supports outline and fill variants with responsive sizes.
  • Grows with its content when resize is auto.
  • Shows helper text and error messages under the textarea.
  • Accepts native attributes such as maxLength.
  • Supports controlled and uncontrolled values.
  • Supports disabled and required states.

Anatomy

<TextArea.Root>
  <TextArea.Label>Project description</TextArea.Label>
  <TextArea.Input name="description" />
  <TextArea.HelperText>Summarize the goal in a few sentences.</TextArea.HelperText>
  <TextArea.ErrorMessage>Enter a valid value.</TextArea.ErrorMessage>
</TextArea.Root>
Component Part
Description
Links the label, helper text, and error to the textarea, and shares size and state.
Names the textarea.
Renders the textarea, submitted under name.
Adds supporting text below the textarea.
Explains the error while error is set.

Variants

Text Area has two visual styles: outline and fill. The default is outline.

<TextArea.Root variant="outline">
  <TextArea.Label>Outline</TextArea.Label>
  <TextArea.Input name="outline-notes" placeholder="Add project notes" />
</TextArea.Root>
<TextArea.Root variant="fill">
  <TextArea.Label>Fill</TextArea.Label>
  <TextArea.Input name="fill-notes" placeholder="Add project notes" />
</TextArea.Root>

Sizes

Root size scales the text, spacing, and label. The default is md.

<TextArea.Root size="sm">
  <TextArea.Label>Small</TextArea.Label>
  <TextArea.Input name="small-notes" rows={2} defaultValue="Review the first draft with the design team." />
</TextArea.Root>
<TextArea.Root size="md">
  <TextArea.Label>Medium</TextArea.Label>
  <TextArea.Input name="medium-notes" rows={2} defaultValue="Review the first draft with the design team." />
</TextArea.Root>

Responsive

size also accepts a breakpoint object.

<TextArea.Root size={{ xs: "sm", md: "md" }}>
  <TextArea.Label>Notes</TextArea.Label>
  <TextArea.Input name="responsive-notes" rows={2} defaultValue="Review the first draft with the design team." />
</TextArea.Root>

Automatic Height

Use Input rows to set the initial height (default: 3). Root resize defaults to "vertical" for manual vertical resizing. Use "auto" to grow with content or "none" for a fixed height with scrolling.

<TextArea.Root resize="auto">
  <TextArea.Label>Growing notes</TextArea.Label>
  <TextArea.Input name="growing-notes" rows={2} placeholder="Add several lines of notes" />
</TextArea.Root>
<TextArea.Root resize="none">
  <TextArea.Label>Fixed-height notes</TextArea.Label>
  <TextArea.Input name="fixed-notes" rows={2} placeholder="Add several lines of notes" />
</TextArea.Root>

Controlled Value and Character Limit

Use value with onChange to control the text. Set limits like maxLength in Input attributes and count from the same state.

0 / 160 characters
"use client";

import { TextArea } from "@vortexlabs/vortex";
import React from "react";

export const TextAreaCountExample = () => {
  const [value, setValue] = React.useState("");
  return (
    <TextArea.Root resize="auto">
      <TextArea.Label>Project summary</TextArea.Label>
      <TextArea.Input
        name="summary"
        value={value}
        onChange={({ value }) => setValue(value)}
        attributes={{ maxLength: 160 }}
      />
      <TextArea.HelperText>{value.length} / 160 characters</TextArea.HelperText>
    </TextArea.Root>
  );
};

Validation

Root error marks the textarea invalid and shows TextArea.ErrorMessage; helper text stays visible. required only adds native validation, so you decide when to set error.

Explain why this change is needed.Include the impact on your team.
<TextArea.Root error required>
  <TextArea.Label>Reason for the change</TextArea.Label>
  <TextArea.Input name="change-reason" />
  <TextArea.ErrorMessage>Explain why this change is needed.</TextArea.ErrorMessage>
  <TextArea.HelperText>Include the impact on your team.</TextArea.HelperText>
</TextArea.Root>

Disabled and Read Only

Root disabled blocks editing and focus. readOnly in Input attributes keeps the text focusable and selectable.

<TextArea.Root disabled>
  <TextArea.Label>Locked notes</TextArea.Label>
  <TextArea.Input name="locked-notes" defaultValue="This project has been archived." />
</TextArea.Root>
<TextArea.Root>
  <TextArea.Label>Release notes</TextArea.Label>
  <TextArea.Input name="release-notes" defaultValue="Added project templates and improved search." attributes={{ readOnly: true }} />
</TextArea.Root>

Accessibility

Key
Description
Tab
Move focus to the textarea. Disabled fields are skipped.
Include TextArea.Label; a placeholder doesn't replace it. Helper text and the error message are linked to the textarea automatically.
Screen readers announce TextArea.ErrorMessage when it appears.