Skip to main content
On this pageOverview

Textarea

Overview

An accessible multi-line text input that links a label and description via ARIA attributes. Textarea is a view-only component with the same three attribute groups as Input — textarea, label, and description — plus a rows prop to control the visible height.

See it in an app

Check out how Textarea is wired up in a real Foldkit app.

Examples

Basic

The toView callback receives attribute groups for the label, description, and textarea element. Spread attributes.textarea onto a <textarea> in your layout to wire up ARIA, focus, and change handling.

A brief introduction about yourself.
// Pseudocode — Textarea is view-only. The value lives in your own Model as
// a string. Replace model.bio and UpdatedBio with your own field and Message.
import { Ui } from 'foldkit'

import { Class, div, label, span, textarea } from './html'

Ui.Textarea.view({
  id: 'bio',
  value: model.bio, // your Model field
  onInput: value => UpdatedBio({ value }), // your Message
  placeholder: 'Tell us about yourself...',
  rows: 4,
  toView: attributes =>
    div(
      [Class('flex flex-col gap-1.5')],
      [
        label([...attributes.label, Class('text-sm font-medium')], ['Bio']),
        textarea(
          [
            ...attributes.textarea,
            Class('w-full rounded-lg border border-gray-300 px-3 py-2'),
          ],
          [],
        ),
        span(
          [...attributes.description, Class('text-sm text-gray-500')],
          ['A brief introduction about yourself.'],
        ),
      ],
    ),
})

Disabled

Set isDisabled: true to disable the textarea. Like Input, this sets both the native disabled attribute and aria-disabled.

This textarea is disabled.
// Pseudocode — Textarea is view-only. Disabled textareas display a fixed
// value and ignore onInput events.
import { Ui } from 'foldkit'

import { Class, label, span, textarea } from './html'

Ui.Textarea.view({
  id: 'bio-disabled',
  isDisabled: true,
  value: 'Known for work on the Analytical Engine.',
  rows: 3,
  toView: attributes =>
    div(
      [Class('flex flex-col gap-1.5')],
      [
        label([...attributes.label, Class('text-sm font-medium')], ['Bio']),
        textarea(
          [
            ...attributes.textarea,
            Class(
              'w-full rounded-lg border px-3 py-2 data-[disabled]:opacity-50',
            ),
          ],
          [],
        ),
        span(
          [...attributes.description, Class('text-sm text-gray-500')],
          ['This textarea is disabled.'],
        ),
      ],
    ),
})

Styling

Textarea is headless — your toView callback controls all markup and styling. Use the data attributes below to style different states.

AttributeCondition
data-disabledPresent when isDisabled is true.
data-invalidPresent when isInvalid is true.

Keyboard Interaction

Textarea uses the native <textarea> element, so all keyboard interaction is handled by the browser.

KeyDescription
TabMoves focus to or away from the textarea.

Accessibility

Textarea provides the same ARIA wiring as Input. The label group links via for, and the description group is referenced by aria-describedby on the textarea. You can access the description ID directly with Textarea.descriptionId(id).

When isInvalid is true, aria-invalid="true" is set on the textarea element.

API Reference

ViewConfig

Configuration object passed to Textarea.view().

NameTypeDefaultDescription
idstring-Unique ID for the textarea element. Used to link the label and description via ARIA attributes.
toView(attributes: TextareaAttributes) => Html-Callback that receives attribute groups for the textarea, label, and description elements.
onInput(value: string) => Message-Function that maps the current textarea value to a Message on each input event.
valuestring-The current value of the textarea.
isDisabledbooleanfalseWhether the textarea is disabled. Sets both the native disabled attribute and aria-disabled.
isInvalidbooleanfalseWhether the textarea is in an invalid state. Sets aria-invalid and adds a data-invalid attribute for styling.
isAutofocusbooleanfalseWhether the textarea receives focus when the page loads.
namestring-The form field name for native form submission.
rowsnumber-The visible number of text lines.
placeholderstring-Placeholder text shown when the textarea is empty.

TextareaAttributes

Attribute groups provided to the toView callback.

NameTypeDefaultDescription
textareaReadonlyArray<Attribute<Message>>-Spread onto the <textarea> element. Includes id, rows, value, ARIA attributes, and event handlers.
labelReadonlyArray<Attribute<Message>>-Spread onto the <label> element. Includes a for attribute linking to the textarea id.
descriptionReadonlyArray<Attribute<Message>>-Spread onto a description element. Includes an id that the textarea references via aria-describedby.

Stay in the update loop.

New releases, patterns, and the occasional deep dive.


Built with Foldkit.

© 2026 Devin Jameson