Textarea
A multi-line native text area, at least 112 px tall, that grows with its content where the browser supports field-sizing and can be resized vertically. Inside a Field it is labelled, described and validated by the Field.
Import
import { Textarea } from '@nizivo/react/textarea';
// Once per app (Getting started), after
// @nizivo/tokens/tokens.css and @nizivo/react/css/base.css
import '@nizivo/react/css/textarea.css';Static or interactive
Client. It always ships its client leaf, which reads its Field through FieldScope, so a page
with a Textarea also loads FieldScope. The server HTML is a native <textarea> that works before
hydration. How to choose.
Height and padding
The box follows Figma's Textarea (7367:316): 12 px padding on every side and a minimum height of
112 px. Its height is the larger of that minimum and rows (3 by default), so up to four rows of
Body/M sit at 112 px and rows={6} is taller. Where the browser supports field-sizing (Chrome and
Edge 123 and later, not Firefox 129 or Safari 17.5) it also grows with its content, never below that
height; elsewhere the user drags it taller. For a one-line box, such as a chat composer, lower the
minimum with the --nz-textarea-min-block-size hook (0 leaves only rows).
.composer .nz-textarea {
--nz-textarea-min-block-size: 0;
}Text size on touch screens
Under a coarse pointer (a phone or a tablet), the text and the placeholder are 16 px (Body/L) instead
of 14 px (Body/M), because iOS Safari zooms the page into a focused field whose text is smaller than
16 px. Each row is then Body/L's 25.6 px line instead of 21 px, so a tall rows grows more there
(Mobile Safari 17.5 rounds each row down to 25 px); the 112 px minimum is the same. --nz-textarea-font replaces the font on every pointer,
so a page that sets it also decides whether iOS zooms.
Examples
Basic
Inside a Field: the label, help text and native validation messages are wired for you.
import type { JSX } from 'react';
import { Field } from '@nizivo/react/field';
import { Textarea } from '@nizivo/react/textarea';
export function TextareaExample(): JSX.Element {
return (
<Field
label="Description"
description="Two or three sentences about the product."
required
messages={{ valueMissing: 'Describe the product.' }}
>
<Textarea name="description" placeholder="Hand-thrown in Bristol, glazed in moss." />
</Field>
);
}
Rows
112 px at least (Figma 7367:316); rows above that sets the height, and the user can drag it taller. Where the browser has field-sizing, it also grows as the text does.
import type { JSX } from 'react';
import { Textarea } from '@nizivo/react/textarea';
export function TextareaRowsExample(): JSX.Element {
return (
<div style={{ display: 'grid', gap: 12, maxInlineSize: 420 }}>
<Textarea aria-label="Short note" placeholder="The 112 px minimum" />
<Textarea rows={6} aria-label="Long note" placeholder="Six rows" />
</div>
);
}
States
An error from the server, read-only and disabled.
import type { JSX } from 'react';
import { Field } from '@nizivo/react/field';
import { Textarea } from '@nizivo/react/textarea';
export function TextareaStatesExample(): JSX.Element {
return (
<div style={{ display: 'grid', gap: 16, maxInlineSize: 420 }}>
<Field label="Care instructions" error="Keep it under 200 characters.">
<Textarea defaultValue="Dishwasher safe. Microwave safe. Not for the oven." />
</Field>
<Field label="Supplier note" readOnly>
<Textarea rows={2} defaultValue="Packed in recycled card." />
</Field>
<Field label="Internal note" disabled>
<Textarea rows={2} defaultValue="Archived." />
</Field>
</div>
);
}
Props
Client component Renders data-slot="textarea" with the class nz-textarea. Props: TextareaProps. Source: src/textarea/textarea.client.tsx.
| Name | Type | Default | Description |
|---|---|---|---|
invalid | boolean | – | An error message is presented for this textarea (§8.3). Inside a Field, the Field sets it; an explicit value here wins. |
rows | number | 3 | Visible lines of text. The height is the larger of these rows and 112 px (Figma 7367:316; the |
- Also takes every attribute of
<textarea>exceptchildren;rowsis redeclared above. (Omit<ComponentPropsWithRef<"textarea">, "children">)
Other exports
TextareaPropstypeimport type { TextareaProps } from '@nizivo/react/textarea'The props of
Textarea, listed above.
Data attributes and slots
Style parts by class (.nz-<slot>) and state by data attribute. Attribute meanings come from contracts/vocabulary.json.
| Slot | Rendered by | Data attributes |
|---|---|---|
textarea.nz-textarea | Textarearoot (no render); interactive, focus: self | none |
CSS hooks
Set a hook on the component's class or any ancestor to restyle it without specificity games; leave it unset for the default shown.
| Hook | Default | Read as |
|---|---|---|
--nz-textarea-bg |
|
|
--nz-textarea-border |
|
|
--nz-textarea-fg | --nz-text-primary |
|
--nz-textarea-font |
|
|
--nz-textarea-min-block-size | 7rem |
|
--nz-textarea-padding-block | --nz-space-3 |
|
--nz-textarea-padding-inline | --nz-space-3 |
|
--nz-textarea-placeholder-fg | --nz-text-tertiary |
|
--nz-textarea-radius | --nz-radius-md |
|
Layers: nz.components. Classes: .nz-textarea.
Tokens this stylesheet reads (20)
--nz-bg-disabled, --nz-bg-subtle, --nz-bg-surface, --nz-border-control, --nz-border-control-hover, --nz-border-critical, --nz-border-subtle, --nz-border-width-default, --nz-border-width-focus, --nz-duration-fast, --nz-easing-standard, --nz-focus-halo, --nz-focus-halo-critical, --nz-font-body-l, --nz-font-body-m, --nz-radius-md, --nz-space-3, --nz-text-disabled, --nz-text-primary, --nz-text-tertiary
Accessibility
These parts are interactive. Each gets the focus outline and touch-action rule from @nizivo/react/css/base.css (the nz.base layer), so the floor survives a restyle:
textarea: draws the focus outline itself on keyboard focus.
Keyboard
| Keys | Action |
|---|---|
| Tab | Moves focus to the text area (Tab is not captured, so it also leaves it). |
| Enter | Starts a new line; it never submits the form. |
Source: a native <textarea> (textarea.client.tsx), which adds no key handling.
Figma
Node ids from design/component-map.json, which nz gen writes from component.json. The links open the Nizivo Figma library, which may ask you to sign in.
- Canonical: none
- Ghost masters: none
Text
Body, label, numeric and mono text in the Nizivo text styles and text colours, as a paragraph or any element through render.
ThemeScript
Sets page-level attributes before first paint, so nothing changes once the page has painted: the reader's saved theme (data-nz-theme from localStorage key nz-theme: light, dark or system) and data-nz-platform (apple or other). The rules are on themeScript. Render it in <head> (<head><ThemeScript nonce={nonce} /></head> in a root layout), put the app's default theme on <html> (data-nz-theme="system", or none for light), and put suppressHydrationWarning on <html>, whose attributes the script changes.