Text Area
A text area takes text that runs over several lines, such as a message, a description or feedback.A text area takes text that runs over several lines: a comment, a bio, a bug report. For a single line, such as a name or an email address, use a Text Field. For a chat composer that grows as people type and takes attachments, use a Chatbar.
Playground
Usage
import { Flex, Text, TextArea } from '@kushagradhawan/kookie-ui';
export function FeedbackField() {
return (
<Flex direction="column" gap="1">
<Text as="label" htmlFor="feedback" size="2" weight="medium">
What could we do better?
</Text>
<TextArea
id="feedback"
rows={5}
maxLength={1000}
/>
</Flex>
);
}Best practices
Give it a visible label. Put the label above the text area and connect it with htmlFor or aria-labelledby. A placeholder disappears once someone starts typing.
Set the height to the answer you expect. Use rows so a short note gets two or three lines and a report gets more. People write less when the box looks small.
Let people make it taller. A text area resizes vertically by default, so people can drag the bottom edge when they write more than you planned for. Set resize="none" for a fixed layout, such as a dialog.
Say what is wrong and how to fix it. Set error and pass an errorMessage such as "Describe the problem in at least 20 characters". Show it after someone leaves the field or submits, not while they type.
Use a Text Field for one line. A text area tells people to write a lot. A name, a title or a search term belongs in a Text Field.
Variant
variant sets the look. The values match Text Field, so both can sit in one form.
| Variant | Use it for |
|---|---|
raised | Most forms. This is the default |
surface | Fields on a plain background that need a clear edge |
soft | Fields inside a card or a panel that already has a border |
outline | Dense forms where a fill would feel heavy |
ghost | Inline editing, such as a note that looks like text until focused |
Size
size sets the text size and padding, and a minimum height of 28, 32, 40 or 48 pixels. Size 2 is the default. Use the same size as the text fields in the same form. rows sets how tall it actually is. size accepts a responsive object, such as { initial: '3', md: '2' }.
Resize
resize sets which way people can drag to resize. It is vertical unless you set it.
| Resize | Effect |
|---|---|
none | Fixed size |
vertical | Taller or shorter. The best choice for most forms |
horizontal | Wider or narrower |
both | Any direction |
resize accepts a responsive object, such as { initial: 'none', md: 'vertical' }.
Examples
Character limit
maxLength stops typing at the limit. Show the count below so people know how much room is left.
const [bio, setBio] = React.useState('');
<Flex direction="column" gap="1">
<TextArea
aria-label="Bio"
value={bio}
onChange={(event) => setBio(event.target.value)}
maxLength={160}
/>
<Text size="1" emphasis="medium">{bio.length} / 160</Text>
</Flex>Validation
error marks the text area as invalid and errorMessage shows below it, linked so a screen reader reads it with the field.
<TextArea
aria-label="Steps to reproduce"
error
errorMessage="Describe what you did before the error appeared"
/>Read-only text
readOnly keeps the text selectable and focusable but stops edits. Use it for something people copy, such as a generated key or a log. Use disabled only when the field doesn't apply right now.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
variant | 'raised' | 'surface' | 'soft' | 'outline' | 'ghost' | 'raised' | The look |
size | '1' | '2' | '3' | '4', responsive | '2' | Text size, padding and minimum height |
resize | 'none' | 'vertical' | 'horizontal' | 'both', responsive | 'vertical' | Which way people can resize it |
color | AccentColor | Theme accent | The colour of the focus ring |
radius | 'none' | 'small' | 'medium' | 'large' | 'full' | Theme radius | The corner |
value | string | The value, when you control it | |
defaultValue | string | The starting value, when the field controls it | |
error | boolean | false | Marks the field as invalid |
errorMessage | string | Text shown below the field and linked to it | |
required | boolean | false | Must be filled before the form submits |
TextArea also accepts every attribute of the HTML textarea element, such as rows, placeholder, maxLength, disabled, readOnly and onChange.
Accessibility
| Key | Action |
|---|---|
| Tab | Moves focus into the text area |
| Enter | Starts a new line |
- Label: The text area renders no label of its own. Connect a visible label with
htmlForandid, or passaria-label. - Errors:
errorsetsaria-invalid. TheerrorMessageelement is linked witharia-describedbyand hasrole="alert", so a screen reader reads it when it appears. - Focus: The focus ring wraps the whole box and uses the field's colour.
- High contrast: In forced colors mode the box draws a real border, since the browser drops its shadows.