Skip to content
weftGitHub

Textarea

Several lines of text that grow as people write.

SourcePackage @weft-js/warpPlayground

Preview

tsx
import { Stack, Textarea } from '@weft-js/warp'export function Rows() {  return (    <Stack gap="group">      <Textarea label="Description" rows={2} defaultValue="The public shop, served from the edge." />      <Textarea label="Description" rows={5} defaultValue="The public shop, served from the edge." />    </Stack>  )}

Installation

npm install @weft-js/warp

Usage

tsx
import { Textarea } from '@weft-js/warp'<Stack gap="group">  <Textarea label="Description" rows={2} defaultValue="The public shop, served from the edge." />  <Textarea label="Description" rows={5} defaultValue="The public shop, served from the edge." /></Stack>

Variants

Use variant and appearance to change the field's style, here classic and line.

tsx
import { Grid, Textarea } from '@weft-js/warp'export function Variants() {  return (    <Grid cols={3} gap="group">      <Textarea label="Description" defaultValue="The public shop." />      <Textarea label="Description" defaultValue="The public shop." variant="classic" />      <Textarea label="Description" defaultValue="The public shop." appearance="line" />    </Grid>  )}

Counter

Use counter to set a character limit and show how much of it is used.

tsx
import { Textarea } from '@weft-js/warp'export function Counter() {  return (    <Textarea label="Release note" counter={140} defaultValue="Product images now load from the edge, about 40% faster." />  )}

States

A textarea can show a hint or an error, and can be disabled or readonly.

tsx
import { Grid, Stack, Text, Textarea } from '@weft-js/warp'export function States() {  return (    <Grid cols={3} gap="group">      <Cell name="Empty"><Textarea label="Description" /></Cell>      <Cell name="Filled"><Textarea label="Description" defaultValue="The public shop, served from the edge." /></Cell>      <Cell name="Hint"><Textarea label="Description" hint="Shown on the project's card." /></Cell>      <Cell name="Invalid"><Textarea label="Description" defaultValue="x" error="Write at least ten characters." /></Cell>      <Cell name="Disabled"><Textarea label="Description" defaultValue="The public shop, served from the edge." disabled /></Cell>      <Cell name="Read-only"><Textarea label="Description" defaultValue="The public shop, served from the edge." readonly /></Cell>    </Grid>  )}const Cell = (p: { name: string; children?: unknown }) => (  <Stack gap="tight">    <Text role="caption" subtle>{p.name}</Text>    {p.children}  </Stack>)

Post a release note

Write something and press ⌘ Enter.

tsx
import { state } from '@weft-js/core'import { Button, Row, Stack, Text, Textarea } from '@weft-js/warp'export function ReleaseNote() {  const text = state('')  const notes = state(['Lowered the stale window to 30s.'])  const post = (e: Event) => {    e.preventDefault()    if (!text.value.trim()) return    notes.value = [text.value.trim(), ...notes.value]    text.value = ''  }  return (    <Stack as="form" gap="group" onSubmit={post}>      <Textarea label="Release note" counter={140} hint="⌘ Enter posts it." value={text.value} onInput={e => (text.value = e.currentTarget.value)} />      <Row justify="end"><Button type="submit" aria-disabled={text.value.trim() ? undefined : 'true'}>Post note</Button></Row>      <Stack gap="tight">        {notes.value.map(n => <Text key={n} subtle>{n}</Text>)}      </Stack>    </Stack>  )}

When to use

Use it for

  • Descriptions, notes and messages

Reach for something else

Playground

Rows3
Variant
import { Textarea } from '@weft-js/warp'<Textarea label="Description" hint="Shown on the project's card." />

Accessibility

Enter
A new line
⌘Enter
Submits its form
  • The same label, hint and error wiring as Input.

API Reference

PropTypeDefaultDescription
labelstring—The name people read and screen readers announce. Always required, and it floats on the border by default.
hintunknown—A short line of help under the field.
errorunknown—Replaces the hint and marks the field invalid.
iconIconRef—Leading icon: it sweeps with the border.
prefixunknown—Text or an element inside the field before the value, such as $.
suffixunknown—Text or an element inside the field after the value, such as kg.
variant"floating" | "classic"—floating puts the label on the border, classic above the field.
appearance"line"—line draws only the bottom edge.
size"sm" | "md" | "lg"—sm, md or lg. Each follows the density around it.
clearablebooleanfalseA clear button (shown once there is a value).
counternumber—The most it should hold. Draws a count under the field.
idstring—The element id. One is made for you if you leave it out.
valuestring—The current value, when you own the state.
disabledbooleanfalseCan't be focused or changed, and doesn't post with a form.
readonlybooleanfalseCan be focused, read and copied, but not changed. It still posts.
placeholderstring—Sample text shown while empty. Never a substitute for a label.
rowsnumber3The starting height in lines.
EventTypeDefaultDescription
onInput((e: InputEvent & { currentTarget: HTMLInputElement & HTMLTextAreaElemen…—Called on each keystroke.

Parts

Every element carries a stable name, so you can style it from your own CSS: [data-scope="textarea"] [data-part="input"]

input

RelatedInputRich text editorMentions input