TextArea
Primitive multiline text input. Apply av-textarea to a native <textarea> element. Accepts standard HTML attributes and implements ControlValueAccessor for Angular forms.
Import
import { AvTextareaComponent } from '@avesra/angular'; For labels, descriptions, and validation errors, compose with av-label, av-description, and av-field-error. For form-level validation and submission, see Form.
Usage
import { Component } from '@angular/core';
import { AvLabelComponent, AvTextareaComponent } from '@avesra/angular';
@Component({
selector: 'app-textarea-basic-demo',
imports: [AvTextareaComponent, AvLabelComponent],
host: { class: 'flex w-full max-w-sm flex-col gap-1' },
template: `<label av-label for="textarea-basic">Description</label>
<textarea
av-textarea
id="textarea-basic"
placeholder="Describe your product"
rows="4"
aria-label="Description"
></textarea>`,
})
export class TextareaBasicDemo {}Anatomy
TextArea uses the av-textarea attribute selector on a native <textarea> element.
<textarea av-textarea rows="4" placeholder="Tell us about yourself"></textarea>Variants
The TextArea component supports two visual variants:
primary(default) — Standard styling with shadow, suitable for most use casessecondary— Lower emphasis variant without shadow, suitable for use in Surface components
import { Component } from '@angular/core';
import { AvTextareaComponent } from '@avesra/angular';
@Component({
selector: 'app-textarea-variants-demo',
imports: [AvTextareaComponent],
host: { class: 'flex w-full max-w-96 flex-col gap-4' },
template: `<textarea av-textarea full-width placeholder="Primary textarea" variant="primary" rows="3"></textarea>
<textarea av-textarea full-width placeholder="Secondary textarea" variant="secondary" rows="3"></textarea>`,
})
export class TextareaVariantsDemo {}In Surface
When used inside a Surface component, use variant="secondary" for the lower-emphasis style that fits surface backgrounds.
import { Component } from '@angular/core';
import { AvSurfaceComponent, AvTextareaComponent } from '@avesra/angular';
@Component({
selector: 'app-textarea-on-surface-demo',
imports: [AvTextareaComponent, AvSurfaceComponent],
host: { class: 'w-full max-w-sm' },
template: `
<div av-surface class="w-full rounded-3xl p-6">
<textarea
av-textarea
full-width
placeholder="Describe your product"
variant="secondary"
rows="4"
></textarea>
</div>
`,
})
export class TextareaOnSurfaceDemo {}Full Width
import { Component } from '@angular/core';
import { AvSurfaceComponent, AvTextareaComponent } from '@avesra/angular';
@Component({
selector: 'app-textarea-full-width-demo',
imports: [AvTextareaComponent, AvSurfaceComponent],
host: { class: 'flex w-full max-w-96 flex-col gap-4' },
template: `<textarea av-textarea full-width placeholder="Full width textarea" rows="4"></textarea>
<div av-surface class="w-full rounded-3xl p-6">
<textarea
av-textarea
full-width
placeholder="Full width textarea on surface"
variant="secondary"
rows="4"
></textarea>
</div>`,
})
export class TextareaFullWidthDemo {}Controlled
Bind with [(ngModel)] or reactive forms — TextArea implements ControlValueAccessor.
Characters: 0 / 280
import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { AvDescriptionComponent, AvTextareaComponent } from '@avesra/angular';
@Component({
selector: 'app-textarea-controlled-demo',
imports: [FormsModule, AvTextareaComponent, AvDescriptionComponent],
host: { class: 'flex w-full max-w-sm flex-col gap-2' },
template: `
<textarea
av-textarea
full-width
aria-label="Announcement"
aria-describedby="textarea-controlled-description"
placeholder="Compose an announcement..."
rows="4"
[(ngModel)]="value"
></textarea>
<p av-description id="textarea-controlled-description">
Characters: {{ value.length }} / 280
</p>
`,
})
export class TextareaControlledDemo {
value = '';
}Rows and Resizing
Control visible height with the native rows attribute. Add a resize utility such as resize-y when vertical resizing should be allowed.
import { Component } from '@angular/core';
import { AvLabelComponent, AvTextareaComponent } from '@avesra/angular';
@Component({
selector: 'app-textarea-rows-demo',
imports: [AvTextareaComponent, AvLabelComponent],
host: { class: 'flex w-full max-w-sm flex-col gap-4' },
template: `
<div class="flex flex-col gap-2">
<label av-label for="textarea-rows-3">Short feedback</label>
<textarea
av-textarea
full-width
id="textarea-rows-3"
aria-label="Short feedback"
placeholder="This week's highlights..."
rows="3"
></textarea>
</div>
<div class="flex flex-col gap-2">
<label av-label for="textarea-rows-6">Detailed notes</label>
<textarea
av-textarea
full-width
id="textarea-rows-6"
class="resize-y"
aria-label="Detailed notes"
placeholder="Write out the full meeting notes..."
rows="6"
></textarea>
</div>
`,
})
export class TextareaRowsDemo {}Customization
Tailwind CSS
<textarea
av-textarea
class="h-28 w-full max-w-xs rounded-xl border border-border/80
bg-surface text-sm shadow-sm ring-1 ring-black/5
placeholder:text-muted
focus-visible:ring-2 focus-visible:ring-neutral-400/25"
aria-label="Notes"
placeholder="Add a note..."
rows="4"
></textarea>Global CSS
Override the shared .av-textarea class once with Tailwind's @layer components.
@layer components {
.av-textarea {
@apply rounded-xl border border-border bg-surface px-4 py-3 text-sm leading-6 shadow-sm;
&:hover,
&[data-hovered="true"] {
@apply bg-surface-secondary border-border/80;
}
&:focus-visible,
&[data-focus-visible="true"] {
@apply border-accent ring-2 ring-accent/20;
}
&[data-invalid="true"] {
@apply border-danger bg-danger-soft text-danger;
}
}
}Styling Reference
Avesra follows the BEM methodology so variants and states stay reusable and easy to customize.
CSS Classes
Base Classes
.av-textarea— Underlying<textarea>element styling.av-textarea--primary— Primary visual variant (default).av-textarea--secondary— Secondary visual variant.av-textarea--full-width— Full-width layout
Interactive States
- Hover:
:hoveror[data-hovered="true"] - Focus Visible:
:focus-visibleor[data-focus-visible="true"] - Invalid:
[data-invalid="true"] - Disabled:
:disabledor[aria-disabled="true"]
API Reference
TextArea accepts standard HTML <textarea> attributes (such as rows, placeholder, readonly, name, maxlength) plus the following Angular inputs. Bind values with [(ngModel)] or reactive forms via ControlValueAccessor.
| Prop | Type | Default | Description |
|---|---|---|---|
variant | 'primary' | 'secondary' | 'primary' | Visual variant. `primary` is the default style with shadow. `secondary` is a lower-emphasis variant without shadow, suitable for surfaces. |
full-width | boolean | false | Whether the textarea should take the full width of its container. |
disabled | boolean | false | Disables the textarea. |
invalid | boolean | false | Marks the textarea as invalid (`aria-invalid` / `data-invalid`). |
For field-level validation UI, compose with av-label, av-description, av-field-error, and optionally Form.