Skip to Content

Text Area

Text Areas allow users to enter and edit multiple lines of text.

Interaction Modes

Creating

Editing

Install

yarn add @workday/canvas-kit-react

Component Type

Input

Platform

Web

Component

Sana Canvas

Delivery Channels

Web

Version

16.1.7

Experience Surfaces

Page Body Inline

Component Type

Input

Platform

Web

Component

Sana Canvas

Delivery Channels

Web

Version

16.1.7

Experience Surfaces

Page Body Inline

Anatomy

Image of a Text Area in its default state with top label.
  1. Label: Title of the Text Area.
  2. Input Container: Rectangular container that houses the placeholder and body text.
  3. Placeholder/Body Text: Placeholder text is optional and shows an example of how the text is used.

Usage Guidance

  • Use the Text Area component when you need to let users enter an amount of text that’s longer than a single line.
  • To ensure we don’t overwhelm users, there shouldn’t be more than two Wide Text Areas on a page.
  • For all Text Areas on Web, a user clicking into a field or label that’s not disabled will trigger the text cursor to appear, allowing users the ability to type. As the user types in the Text Area, the placeholder text is replaced with the user’s input.

When to Use

  • Use the Text Area to fit longer text descriptions, usually around one paragraph.

When to Use Something Else

  • Use a Rich Text Editor to give users the ability to format text.
  • Use a Text Input for single line of text.

Examples

Basic Example

Text Area should be used in tandem with Form Field to ensure proper label association and screen reader support.

import React from 'react';

import {FormField} from '@workday/canvas-kit-react/form-field';
import {TextArea} from '@workday/canvas-kit-react/text-area';

export default () => {
  const [value, setValue] = React.useState('');

  const handleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
    setValue(event.target.value);
  };

  return (
    <FormField>
      <FormField.Label>Leave a Review</FormField.Label>
      <FormField.Field>
        <FormField.Input as={TextArea} onChange={handleChange} value={value} />
      </FormField.Field>
    </FormField>
  );
};

Disabled

Set the disabled prop of the Text Area to prevent users from interacting with it.

import React from 'react';

import {FormField} from '@workday/canvas-kit-react/form-field';
import {TextArea} from '@workday/canvas-kit-react/text-area';

export default () => {
  const [value, setValue] = React.useState('');

  const handleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
    setValue(event.target.value);
  };

  return (
    <FormField>
      <FormField.Label>Leave a Review</FormField.Label>
      <FormField.Field>
        <FormField.Input as={TextArea} disabled onChange={handleChange} value={value} />
      </FormField.Field>
    </FormField>
  );
};

Placeholder

Set the placeholder prop of the Text Area to display a sample of its expected format or value before a value has been provided.

import React from 'react';

import {FormField} from '@workday/canvas-kit-react/form-field';
import {TextArea} from '@workday/canvas-kit-react/text-area';

export default () => {
  const [value, setValue] = React.useState('');

  const handleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
    setValue(event.target.value);
  };

  return (
    <FormField>
      <FormField.Label>Leave a Review</FormField.Label>
      <FormField.Field>
        <FormField.Input
          as={TextArea}
          onChange={handleChange}
          placeholder="Let us know how we did!"
          value={value}
        />
      </FormField.Field>
    </FormField>
  );
};

Accessibility Note: Always provide a persistent FormField.Label and never rely on placeholder text as the only label for a text area. Placeholders can disappear or lack sufficient contrast. Use placeholders only for short format examples, and place detailed instructions or guidance in FormField.Hint instead of the placeholder.

Ref Forwarding

Text Area supports ref forwarding . It will forward ref to its underlying <textarea> element.

import React from 'react';

import {PrimaryButton} from '@workday/canvas-kit-react/button';
import {FormField} from '@workday/canvas-kit-react/form-field';
import {TextArea} from '@workday/canvas-kit-react/text-area';

export default () => {
  const [value, setValue] = React.useState('');
  const ref = React.useRef(null);

  const handleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
    setValue(event.target.value);
  };

  const handleClick = () => {
    ref.current.focus();
  };

  return (
    <>
      <FormField>
        <FormField.Label>Leave a Review</FormField.Label>
        <FormField.Field>
          <FormField.Input as={TextArea} onChange={handleChange} ref={ref} value={value} />
        </FormField.Field>
      </FormField>
      <PrimaryButton onClick={handleClick}>Focus Text Area</PrimaryButton>
    </>
  );
};

Resize Constraints

Set the resize prop of the Text Area to restrict resizing of it to certain dimensions. resize accepts the following values:

  • TextArea.ResizeDirection.Both (Default)
  • TextArea.ResizeDirection.Horizontal
  • TextArea.ResizeDirection.None
  • TextArea.ResizeDirection.Vertical
import React from 'react';

import {FormField} from '@workday/canvas-kit-react/form-field';
import {TextArea} from '@workday/canvas-kit-react/text-area';

export default () => {
  const [value, setValue] = React.useState('');

  const handleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
    setValue(event.target.value);
  };

  return (
    <FormField>
      <FormField.Label>Leave a Review</FormField.Label>
      <FormField.Field>
        <FormField.Input
          as={TextArea}
          onChange={handleChange}
          resize={TextArea.ResizeDirection.Vertical}
          value={value}
        />
      </FormField.Field>
    </FormField>
  );
};

Accessibility Note: Allowing users to resize the text area (default resize: both) improves accessibility by letting them adjust it for comfort. Avoid disabling resizing (resize: none) unless necessary, and always ensure the initial size meets the needs of your content.

Grow

Set the grow prop of the Text Area to true to configure the Text Area to expand to the width of its container.

import React from 'react';

import {FormField} from '@workday/canvas-kit-react/form-field';
import {TextArea} from '@workday/canvas-kit-react/text-area';

export default () => {
  const [value, setValue] = React.useState('');

  const handleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
    setValue(event.target.value);
  };

  return (
    <FormField grow>
      <FormField.Label>Leave a Review</FormField.Label>
      <FormField.Field>
        <FormField.Input as={TextArea} onChange={handleChange} value={value} />
      </FormField.Field>
    </FormField>
  );
};

Label Position Horizontal

Set the orientation prop of the Form Field to designate the position of the label relative to the input component. By default, the orientation will be set to vertical.

Message must be under 200 characters

import React from 'react';

import {FormField} from '@workday/canvas-kit-react/form-field';
import {TextArea} from '@workday/canvas-kit-react/text-area';

export default () => {
  const [value, setValue] = React.useState('');

  const handleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
    setValue(event.target.value);
  };

  return (
    <FormField orientation="horizontalStart">
      <FormField.Label>Leave a Review</FormField.Label>
      <FormField.Field>
        <FormField.Input as={TextArea} onChange={handleChange} value={value} />
        <FormField.Hint>Message must be under 200 characters</FormField.Hint>
      </FormField.Field>
    </FormField>
  );
};

Required

Set the isRequired prop of the wrapping Form Field to true to indicate that the field is required. Labels for required fields are suffixed by a red asterisk.

import React from 'react';

import {FormField} from '@workday/canvas-kit-react/form-field';
import {TextArea} from '@workday/canvas-kit-react/text-area';

export default () => {
  const [value, setValue] = React.useState('');

  const handleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
    setValue(event.target.value);
  };

  return (
    <FormField isRequired={true}>
      <FormField.Label>Leave a Review</FormField.Label>
      <FormField.Field>
        <FormField.Input as={TextArea} onChange={handleChange} value={value} />
      </FormField.Field>
    </FormField>
  );
};

Error States

Form Field provides error and caution states for Text Area. Set the error prop on Form Field to "error" or "caution" and use FormField.Hint to provide error messages. See Form Field’s Error documentation for examples and accessibility guidance.

Accessibility

The primary accessibility goal for TextArea is to give every user a visible, persistent label and clear instructions, and to ensure assistive technology users can identify the multi-line field and hear hints, errors, required state, and character-limit information when the control receives focus. Use TextArea when users need to enter multiple lines or paragraphs of text. For single-line values (names, emails, short answers), use TextInput instead.

Minimum Accessible Structure

Build on the Basic example: label first, then the input inside FormField.Field. This order matches the DOM reading sequence and ensures the label’s htmlFor targets the <textarea> before hint text follows the control.

import {FormField} from '@workday/canvas-kit-react/form-field'; import {TextArea} from '@workday/canvas-kit-react/text-area'; <FormField> <FormField.Label>Leave a Review</FormField.Label> <FormField.Field> <FormField.Input as={TextArea} /> <FormField.Hint>Share any additional feedback.</FormField.Hint> </FormField.Field> </FormField>;

Every TextArea requires FormField, a visible FormField.Label, and FormField.Input as={TextArea} so the control has a programmatically determinable name, relationships, and instructions. See FormField’s accessibility documentation for shared form-field guidance. Include FormField.Hint for instructions, validation messages, or character counts—FormField associates that text with the text area through aria-describedby.

Built-in Behaviors

Canvas Kit applies these automatically when you compose TextArea with FormField subcomponents. Do not duplicate them in consuming code.

ARIA and DOM (applied by subcomponents):

  • TextArea: Renders a native <textarea> element. Screen readers identify it as a multi-line text input.
  • TextArea disabled: Maps to the native disabled attribute; disabled fields are removed from the tab order.
  • User-resizable dimensions: Defaults to resize: both so users can adjust the control for visual comfort.

Keyboard (standard TextArea behavior):

Enter: Inserts a new line (native <textarea> behavior). Do not add custom key handlers that prevent standard text editing.

TextArea uses native <textarea> keyboard behavior (tab order, label activation, and text-editing shortcuts).

Screen reader expectations (when built-in behaviors are used as intended):

  • On focus, assistive technology announces the field label and, when applicable: required state, invalid state (error="error"), and hint or error text via aria-describedby.
  • The current value or “blank” is announced when the text area receives focus.
  • The Caution state is visual only — aria-invalid is not set for error="caution".
  • Disabled text areas may be announced as unavailable and are skipped in the tab order.

For rendered label, input, and hint association markup, see the DOM examples in FormField’s Built-in Behaviors. TextArea renders a native <textarea> in place of <input>.

Accessibility Requirements

Required in application code for an accessible TextArea. Rows marked (conditional) apply only when the situation matches—otherwise omit.

If no design spec is provided: use a visible FormField.Label, wrap the control with FormField.Input as={TextArea}, omit isHidden, keep default resize: both, omit a custom id unless testing or composition requires it, and omit a ref unless programmatic focus is required.

Programmatic focus (conditional — omit by default):

Use a ref when the product needs to move focus to the text area after an action (for example, focusing the field after a validation error, or a control that focuses the text area). Do not attach a ref or call focus() unless the design or developer asks for it. See Ref Forwarding under Usage for a complete Storybook example.

const Example = () => { const ref = React.useRef<HTMLTextAreaElement>(null); const handleClick = () => { ref.current?.focus(); }; return ( <> <FormField> <FormField.Label>Leave a Review</FormField.Label> <FormField.Field> <FormField.Input as={TextArea} ref={ref} /> </FormField.Field> </FormField> <PrimaryButton onClick={handleClick}>Focus Text Area</PrimaryButton> </> ); };
RequirementHow to satisfy
Input wiringFormField.Input as={TextArea} wrapping every TextArea instance. See FormField accessibility for label, hint, error, and required wiring
Character limit (conditional)maxLength on FormField.Input, visible count in FormField.Hint, and debounced AriaLiveRegion. See Aria Live Regions guide
Programmatic focus (conditional)ref on FormField.Input and call focus() when moving focus to the field after an action—omit by default (see Programmatic focus above)

Summary for code generation:

  • REQUIRED: visible label, FormField.Input as={TextArea} wiring
  • CONDITIONAL: character limit with live region, programmatic focus via ref. See FormField accessibility for shared FormField conditionals (hint/error, required, disabled, placeholder, stable id).

Anti-Patterns

Do not generate code that does the following (see Accessibility Requirements above for what to supply instead):

  • Unlabeled text areas: Do not use TextArea without FormField and FormField.Label (see Minimum accessible structure). For shared FormField anti-patterns (manual ARIA wiring, placeholder-only labels, color-only errors, broken ID references), see FormField Anti-Patterns.
  • Single-line input for multi-line content: Do not use TextInput when the user needs to enter paragraphs or multi-line text; use TextArea instead.
  • Per-keystroke character announcements: Do not announce character counts after every keystroke; debounce AriaLiveRegion updates so screen reader users are not interrupted while typing.
  • Disabling resize unnecessarily: Do not set resize to none unless there is a strong design or layout requirement; users lose a visual comfort affordance that supports low-vision and motor needs.
  • Programmatic focus by default: Do not attach a ref or call focus() on the text area unless the design or developer asks for it (see Programmatic focus in Accessibility Requirements).

Component API

TextArea

Props

Props extend from textarea. Changing the as prop will change the element interface.

NameTypeDescriptionDefault
error

The type of error associated with the TextArea (if applicable).

resize

The resize constraints of the TextArea.

growboolean

True if the component should grow to its container's width. False otherwise.

childrenReact.ReactNode
asReact.ElementType

Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

textarea
refReact.Ref<R = textarea>

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

TextArea.ErrorType

Basic type information:

ErrorType

TextArea.ResizeDirection

NameTypeDescriptionDefault
None'none'
'none'
Both'both'
'both'
Horizontal'horizontal'
'horizontal'
Vertical'vertical'
'vertical'