Multiline text entry. Same contract as the input field — the deltas are multiline metrics: relaxed line height, a three-control minimum height, and native vertical resizing. Width remains owned by the container, so resizing cannot pull the control out of its inline layout.
The state vocabulary is Input's; only the content wraps.
| Example | State | Driver | Roles | Usage |
|---|---|---|---|---|
| Rest | — | border.defaulttext.muted | Placeholder is never essential content | |
| Rest, filled | — | text.primary | Content wraps; the user may increase the height | |
| Hover | :hover | border.hover | The border answers the pointer | |
| Focus | :focus-visible | focus.ring | The engaged control — the border takes the focus color, no offset ring | |
| Invalid | [aria-invalid] | status.error.border.fg | Pair with an error message via aria-describedby | |
| Read-only | [readonly] | surface.canvas | Generated content: copyable, not editable | |
| Disabled | :disabled | action.disabled.bg.text | Excluded from interaction and the tab order |
Drag the native handle to resize vertically. Content past the current height still scrolls inside the box; size.control.md × 3 is only the floor.
A textarea is Input, given room — the deltas are metric, not behavioral.
| Verdict | Rule |
|---|---|
| Do | Apply Input's rules unchanged — the label via FormField, the placeholder as a hint, aria-invalid paired with a message via aria-describedby. |
| Do | Reserve textarea for genuinely multiline content — a generous-feeling single-line answer belongs in an input. |
| Do | Size the control for the content you expect — min-height (size.control.md × 3) is a floor, not a ceiling, and keep the vertical resize handle available. |
| Don’t | Enable horizontal resizing or disable resizing per instance — width belongs to the layout, while height remains adjustable by the user. |