---
layout: ~/layouts/MdxDocLayout.astro
title: "InputArea"
description: "A multi-line text input for longer content with built-in label, description, and error support."
sourceFile: "components/input"
---

import ComponentExample from "~/components/docs/ComponentExample.astro";
import ComponentSection from "~/components/docs/ComponentSection.astro";
import Heading from "~/components/docs/Heading.astro";
import PropsTable from "~/components/docs/PropsTable.astro";
import {
  InputAreaBasicDemo,
  InputAreaWithLabelDemo,
  InputAreaErrorStringDemo,
  InputAreaErrorObjectDemo,
  InputAreaSizesDemo,
  InputAreaDisabledDemo,
  InputAreaBareDemo,
  InputAreaRowsDemo,
  InputAreaOptionalFieldDemo,
  InputAreaLabelTooltipDemo,
  InputAreaReactNodeLabelDemo,
} from "~/components/demos/InputAreaDemo";

{/* Hero Demo */}

<ComponentSection>
  <ComponentExample demo="InputAreaBasicDemo">
    <InputAreaBasicDemo client:visible />
  </ComponentExample>
</ComponentSection>

{/* Installation */}

<ComponentSection>
  <Heading level={2}>Installation</Heading>
  <Heading level={3}>Barrel</Heading>

```tsx
import { InputArea } from "@cloudflare/kumo";
```

<Heading level={3}>Granular</Heading>

```tsx
import { InputArea } from "@cloudflare/kumo/components/input";
```

`Textarea` is also exported as an alias for `InputArea` for discoverability when migrating from other libraries.

</ComponentSection>

{/* Usage */}

<ComponentSection>
  <Heading level={2}>Usage</Heading>
  <Heading level={3}>With Built-in Field (Recommended)</Heading>

<p>
  Use the `label` prop to enable the built-in Field wrapper with label,
  description, and error support.
</p>

```tsx
import { InputArea } from "@cloudflare/kumo";

export default function Example() {
  return (
    <InputArea
      label="Description"
      placeholder="Enter a description..."
      description="Provide details about your project"
    />
  );
}
```

<Heading level={3}>Bare InputArea (Custom Layouts)</Heading>

<p>
  For custom form layouts, use InputArea without `label`. Must provide
  `aria-label` or `aria-labelledby` for accessibility.
</p>

```tsx
import { InputArea } from "@cloudflare/kumo";

export default function Example() {
  return <InputArea placeholder="Add notes..." aria-label="Notes" rows={3} />;
}
```

</ComponentSection>

{/* Examples */}

<ComponentSection>
  <Heading level={2}>Examples</Heading>

<Heading level={3}>With Label</Heading>
<ComponentExample demo="InputAreaWithLabelDemo">
  <InputAreaWithLabelDemo client:visible />
</ComponentExample>

<Heading level={3}>Custom Row Count</Heading>
<p>Use the `rows` prop to control the initial height.</p>
<ComponentExample demo="InputAreaRowsDemo">
  <InputAreaRowsDemo client:visible />
</ComponentExample>

<Heading level={3}>Error State (String)</Heading>
<p>Error styling is automatically applied when the `error` prop is truthy.</p>
<ComponentExample demo="InputAreaErrorStringDemo">
  <InputAreaErrorStringDemo client:visible />
</ComponentExample>

<Heading level={3}>Error State (Object)</Heading>
<p>Use an error object with `match` for constraint validation.</p>
<ComponentExample demo="InputAreaErrorObjectDemo">
  <InputAreaErrorObjectDemo client:visible />
</ComponentExample>

<Heading level={3}>Sizes</Heading>
<p>Four sizes available: `xs`, `sm`, `base` (default), `lg`.</p>
<ComponentExample demo="InputAreaSizesDemo">
  <InputAreaSizesDemo client:visible />
</ComponentExample>

<Heading level={3}>Disabled</Heading>
<ComponentExample demo="InputAreaDisabledDemo">
  <InputAreaDisabledDemo client:visible />
</ComponentExample>

<Heading level={3}>Bare InputArea</Heading>
<p>
  InputArea without `label` renders as a bare textarea. Must provide
  `aria-label` for accessibility.
</p>
<ComponentExample demo="InputAreaBareDemo">
  <InputAreaBareDemo client:visible />
</ComponentExample>

<Heading level={3}>Optional Field</Heading>
<p>Set `required={false}` to show "(optional)" text after the label.</p>
<ComponentExample demo="InputAreaOptionalFieldDemo">
  <InputAreaOptionalFieldDemo client:visible />
</ComponentExample>

<Heading level={3}>Label with Tooltip</Heading>
<p>Use `labelTooltip` to add an info icon with additional context on hover.</p>
<ComponentExample demo="InputAreaLabelTooltipDemo">
  <InputAreaLabelTooltipDemo client:visible />
</ComponentExample>

<Heading level={3}>React Node Label</Heading>
<p>The `label` prop accepts ReactNode for rich formatting.</p>
<ComponentExample demo="InputAreaReactNodeLabelDemo">
  <InputAreaReactNodeLabelDemo client:visible />
</ComponentExample>

</ComponentSection>

{/* API Reference */}

<ComponentSection>
  <Heading level={2}>API Reference</Heading>

<p>
  InputArea accepts all standard HTML textarea attributes plus the following:
</p>

<PropsTable component="InputArea" />

</ComponentSection>

{/* Accessibility */}

<ComponentSection>
  <Heading level={2}>Accessibility</Heading>

<h3 class="mb-2 font-semibold">Label Requirement</h3>

<p class="text-kumo-strong">
  InputArea requires an accessible name via one of:
</p>

<ul class="ml-4 list-disc space-y-1 text-kumo-strong">
  <li>`label` prop (recommended)</li>
  <li>`placeholder` + `aria-label` for bare textareas</li>
  <li>`aria-labelledby` for custom label association</li>
</ul>

<p class="mt-2 text-kumo-strong">
  Missing accessible names trigger console warnings in development.
</p>

<h3 class="mb-2 mt-4 font-semibold">Error Association</h3>

<p class="text-kumo-strong">
  Error messages are automatically associated with the textarea via ARIA
  attributes for screen reader announcement.
</p>

</ComponentSection>
