Default
Show the codeHide the code
Default, code
<TextArea label="Message" hint="Tell us what you need help with." />Multi-line text with a label, hint, error and an optional character count announced politely.
These are the real React components. Use them with a mouse, touch or keyboard, and switch the theme and density for every example at once.
Default, code
<TextArea label="Message" hint="Tell us what you need help with." />With a character count, code
<TextArea
label="Bio"
maxLength={160}
showCount
defaultValue="Product designer in Leeds. I like small tools that do one thing well."
/>Invalid, code
<TextArea label="Message" isRequired isInvalid errorMessage="Enter a message" />Disabled, code
<TextArea label="Message" isDisabled defaultValue="This note is locked." />The 4 design tokens TextArea reads, with the value each has in the theme and density chosen above. Change a token and the component follows, in Figma and in code.
| Token | Value now | CSS variable |
|---|---|---|
| field.hint | … | --sd-field-hint |
| font.line-height.normal | … | --sd-font-line-height-normal |
| input.height | … | --sd-input-height |
| spacing.inset.sm | … | --sd-spacing-inset-sm |
The npm package isn’t published yet. When it is, this is the install line; until then, this page runs the same build of the package (from commit fa3abf8).
Install
npm i @superduperui/react @superduperui/tokensImport
import { TextArea } from "@superduperui/react"TextArea also takes the props of the React Aria component it’s built on.
| Prop | Type | What it does |
|---|---|---|
labelrequired | string | Visible label (required). |
hint | string | |
errorMessage | string | ((validation: ValidationResult) => string) | |
placeholder | string | |
rows | numberDefault 4 | Visible rows before it scrolls. Default 4. |
showCount | boolean | With maxLength: show "n of max characters"; screen readers hear the count politely when 20 or fewer remain. |
hideLabel | boolean | Keep the label for assistive technology but hide it visually. |
textAreaRef | Ref<HTMLTextAreaElement> |
Screen readers announce "Bio, edit text, multi-line"; near the limit "5 characters left".
WCAG 2.2 AAA criteria the component meets in Comfortable density: 1.4.6, 1.4.9, 2.1.3, 2.3.2, 2.4.13, 2.5.5, 2.5.6.
Compact density meets AA (2.5.8, 24px targets), not AAA.
Shared patterns it ships with: 1.4.8 (70ch measure, 1.5 leading); 3.3.5 (hint and count).
| axe-core (WCAG A, AA, AAA and best practice) | 100 runs across every story, theme, density and width: 0 violations |
|---|---|
| Rendered text contrast | 305 text runs: 0 below 7:1, lowest 8.43:1 |
| Target size | 26 targets: 0 under 44px in Comfortable |
| Focus appearance (2.4.13) | 18 focus stops in 3 browser engines: all pass |
| Keyboard script | Chromium 4 of 4, Firefox 4 of 4, WebKit 4 of 4 |
Manual passes with VoiceOver and NVDA haven’t been done yet.
Each step is scripted and run in Chromium, Firefox and WebKit.
| Key | What happens |
|---|---|
| Tab | Tab reaches the text area |
| End | End moves to the end of the line |
| Typing adds text and the visible count follows | |
| Enter | Enter adds a new line (it never submits) |
The Figma component is TextArea, with State (Default, Hover, Focus, Disabled, Invalid); Label visibility (Visible, Hidden); Content (Placeholder, Value). The Figma library isn’t published yet.
Figma to code: State (Default, Hover, Focus, Disabled = isDisabled, Invalid = isInvalid); Label visibility → hideLabel (Visible = false, Hidden = true); Content (Placeholder, Value; preview only); Value → defaultValue; Placeholder → placeholder; Show count → showCount; Count → maxLength (the limit the drawn count implies: "n of max characters", or what is left plus what is typed) when Show count; nested Label → label; nested Hint → hint; nested FieldError → errorMessage.