Textarea
A standalone Angular component over a native textarea, with Form Field, accessible counter, validation, and ControlValueAccessor.
Design
Functional preview
Running with the native Angular component and HTML textarea + Angular Forms.
Anatomy
.ds-textarea) -- same border/radius pattern as Input.2 Field (
.ds-textarea__field) -- the native <textarea> element.3 Resize handle -- browser-native, vertical only by default.
4 Label (
.ds-field__label) -- external, via Form Field.5 Error message (
.ds-field__error) -- external, via Form Field.6 Helper text (
.ds-field__helper) -- external, via Form Field.Character counter (optional,
.ds-field__counter) -- available via Form Field wrapper.
Default
Sizes
| Size | Min-height | Use case |
|---|---|---|
Small (--sm) | 80px | Short inputs: feedback ratings, brief comments |
Medium (--md) | 120px | Standard use: messages, descriptions (default) |
Large (--lg) | 160px | Long-form content: bios, detailed feedback |
Character Counter
States
In Figma, State only represents exclusive visual states: Default, Hover, Focus, and Disabled. Filled, Error, and Read-only are separate properties; Error combines with Default/Hover/Focus, and Read-only combines with Default/Focus.
Error
Disabled
Readonly
| Figma property | Value / CSS trigger | Visual change | Token |
|---|---|---|---|
| State | Default | Neutral surface and border | component.field.bg.default, component.field.border-color.default |
| State | Hover / :hover | Darker border | component.field.border-color.hover |
| State | Focus / :focus-within | 2px outline ring, component radius | component.field.border-color.focus, component.focus-ring.*, component.textarea.focus-ring.radius.default |
| State | Disabled / [disabled] or .ds-textarea--disabled | Muted bg, border and content | component.field.bg.disabled, component.field.value.color.disabled |
| Error | True / .ds-textarea--error or .ds-field--error .ds-textarea | Red border and error focus ring | component.field.border-color.error, component.focus-ring.color.error |
| Error + State | True + Hover / .ds-textarea--error:hover | Darker red border | component.field.border-color.error-hover |
| Read-only | True / [readonly] or .ds-textarea--readonly | Readonly bg with neutral focus ring | component.field.bg.readonly, component.focus-ring.color.readonly |
Figma properties
| Property | Type | Default | Description |
|---|---|---|---|
Show Label | Boolean | true | Shows or hides the label row (including required asterisk) |
Label | Text | "Rótulo" | Label text (label/md) |
Required | Boolean | false | Shows * in feedback/error/content/default next to the label |
Show Helper Text | Boolean | true | Shows or hides the helper text below the control |
Helper Text | Text | "Texto auxiliar" | Caption/sm annotation (content/secondary) |
Usage
When to use
Best practices
Content guidelines
| Rule | Example |
|---|---|
| Labels follow the same rules as Input | "Message", "Description", "Bio" -- not "Enter your message here" |
| Placeholders can be slightly longer (wider field) | "Tell us about your experience..." -- not just "Type here" |
| Error messages describe what went wrong and how to fix | "Message must be at least 20 characters." -- not "Error" |
| Character counter format: current / max | "42 / 200" -- not "42 characters" or "158 remaining" |
Over-limit counter uses ds-field__counter--over | Counter turns red when current > max |
Related
When to choose this output
Choose this native Angular output when the application already uses Angular. It consumes the same DS CSS and has no dependency on the Web runtime or React adapters.
Implementation
- Status
- Beta
- Distribution
- Validated Angular tarball
Installation
npm install ./dist/tis-angular-0.0.0-beta.0.tgz ds-tispnpm add ./dist/tis-angular-0.0.0-beta.0.tgz ds-tisyarn add ./dist/tis-angular-0.0.0-beta.0.tgz ds-tisbun add ./dist/tis-angular-0.0.0-beta.0.tgz ds-tisDS styles
@import "ds-tis/css";Angular imports
import { FormsModule } from '@angular/forms'
import { TisTextarea } from '@tis/angular/textarea'Template
<tis-textarea
name="message"
label="Mensagem"
[(ngModel)]="message"
helperText="Máximo de 500 caracteres."
[maxLength]="500"
[showCounter]="true"
/>Public contract
- Package
@tis/angular- Entrypoint
@tis/angular/textarea- Primitive
HTML textarea + Angular Forms- Status
- Beta
Accessibility
Keyboard interaction
| Key | Action |
|---|---|
Tab | Moves focus into / out of the textarea |
Enter | Inserts a new line (does NOT submit the form) |
| Any character | Types into the field |
Unlike single-line inputs, pressing Enter inside a textarea creates a new line instead of submitting the form. This is native browser behavior.
Accessibility
| WCAG criterion | Requirement | Status |
|---|---|---|
| 1.3.1 Info and Relationships (A) | Every textarea must have a visible <label> with matching for/id. | ✓ |
| 1.3.5 Identify Input Purpose (AA) | Use autocomplete attributes where applicable (e.g. autocomplete="street-address"). | ✓ |
| 1.4.3 Contrast (AA) | Text and placeholder meet 4.5:1 and 3:1 contrast respectively. | ✓ |
| 2.4.11 Focus Appearance (AA) | Focus ring 2px + 2px gap, contrast ≥ 3:1 against adjacent colors. | ✓ |
| 3.3.1 Error Identification (A) | Error state uses aria-invalid="true" + aria-describedby linking to the error message. | ✓ |
| 3.3.2 Labels or Instructions (A) | Placeholder is supplemental, never a replacement for the label. | ✓ |
| 4.1.3 Status Messages (AA) | Character counter uses aria-live="polite" so screen readers announce updates. | ✓ |
aria-invalid="true" -- set when the field has a validation error.aria-describedby -- references the error message or helper text element ID.aria-live="polite" -- on the character counter for dynamic screen reader updates.If
maxlength is set on the native element, browsers enforce the limit -- no JS validation needed.
Required = true, add aria-required="true" to the <textarea> — the visual asterisk (.ds-field__required) is decorative (aria-hidden="true"). When Show Label = false, use aria-label on the <textarea>. Helper Text should be linked via aria-describedby.
Output responsibility
Preserve native button semantics, submit behavior, accessible names, disabled state, and visible focus.
Validation evidence
Covered by its independent Storybook output plus browser, responsive, keyboard, Axe, and bundle checks.