Primitives
13
Textarea
The field's twin, minus the fixed height. resize: vertical only — a textarea that can be dragged wider escapes whatever laid it out. autoGrow makes it grow with the content instead, in CSS: field-sizing: content is the whole implementation, so there is no keystroke handler measuring scrollHeight, and it keeps working in markup that was never hydrated. Where the property is unsupported the control stays a fixed box with a scrollbar.
plain markup — no library on the page
rendered by aura-react
rendered by aura-vue
rendered by aura-svelte
built from aura-angular's own class helpers
Code
index.html
<div class="aura-stack" style="--aura-dir:column;--aura-gap:var(--space-4);min-width:320px;">
<div class="aura-field-group">
<label class="aura-label" for="notes">Notes</label>
<textarea id="notes" class="aura-textarea" rows="4" placeholder="Anything worth remembering"></textarea>
</div>
<div class="aura-field-group">
<label class="aura-label" for="notes-grow">Notes, growing</label>
<textarea id="notes-grow" class="aura-textarea aura-textarea--autogrow" rows="2" placeholder="Type a few lines"></textarea>
</div>
</div>Demo.tsx
import { Stack, Textarea } from '@ilomee/aura-react';
export default function Demo() {
// `autoGrow` is CSS, not a keystroke handler — which is why it also works in the panels
// rendered at build time and never hydrated. Type a few lines into either one.
return (
<Stack gap={4} style={{ minWidth: 320 }}>
<Textarea label="Notes" rows={4} placeholder="Anything worth remembering" />
<Textarea label="Notes, growing" rows={2} autoGrow placeholder="Type a few lines" />
</Stack>
);
}Demo.vue
<script setup lang="ts">
import { ref } from 'vue';
import { Textarea } from '@ilomee/aura-vue';
const notes = ref('');
</script>
<template>
<Textarea v-model="notes" label="Notes" :rows="2" auto-grow />
</template>Demo.svelte
<script lang="ts">
import { Textarea } from '@ilomee/aura-svelte';
let notes = $state('');
</script>
<Textarea bind:value={notes} label="Notes" rows={2} autoGrow />Used as aura-textarea.
demo.component.ts
import { AuraTextarea } from '@ilomee/aura-angular';
@Component({
standalone: true,
imports: [AuraTextarea],
template: `<aura-textarea label="Notes" rows="2" autoGrow [(value)]="notes" />`,
})
export class DemoComponent {
notes = '';
}Props
Plain markup has no props — the classes below are the whole API. The four packages do nothing more than set these same classes for you.
| Name | Type | Default | Notes |
|---|---|---|---|
| label | string | — | |
| hint | string | — | Standing help under the control, always shown. |
| error | string | — | What is wrong right now. Sets aria-invalid on the control and adds the message to its aria-describedby, after the hint. No live region: role="alert" announces on mount, so a server-rendered form with three errors would interrupt three times before the reader reached the first field. |
| value | string | — | |
| defaultValue | string | — | |
| onValueChange | (value: string) => void | — | |
| id | string | — | The generated id comes from the framework itself, so it is stable across SSR and hydration. |
| autoGrow | boolean | false | Grows with the content instead of scrolling — field-sizing: content, no keystroke handler. Where the browser lacks it the textarea stays a fixed box with a scrollbar. |
| inputClassName | string | — |
| Name | Type | Default | Notes |
|---|---|---|---|
| label | string | — | |
| hint | string | — | Standing help under the control, always shown. |
| error | string | — | What is wrong right now. Sets aria-invalid on the control and adds the message to its aria-describedby, after the hint. No live region: role="alert" announces on mount, so a server-rendered form with three errors would interrupt three times before the reader reached the first field. |
| modelValuetwo-way | string | — | |
| defaultValue | string | — | |
| id | string | — | The generated id comes from the framework itself, so it is stable across SSR and hydration. |
| autoGrow | boolean | false | |
| update:modelValueevent | (value: string) => void | — |
| Name | Type | Default | Notes |
|---|---|---|---|
| label | string | — | |
| hint | string | — | Standing help under the control, always shown. |
| error | string | — | What is wrong right now. Sets aria-invalid on the control and adds the message to its aria-describedby, after the hint. No live region: role="alert" announces on mount, so a server-rendered form with three errors would interrupt three times before the reader reached the first field. |
| valuetwo-way | string | '' | |
| id | string | — | The generated id comes from the framework itself, so it is stable across SSR and hydration. |
| autoGrow | boolean | false |
| Name | Type | Default | Notes |
|---|---|---|---|
| label | string | — | |
| hint | string | — | Standing help under the control, always shown. |
| error | string | — | What is wrong right now. Sets aria-invalid on the control and adds the message to its aria-describedby, after the hint. No live region: role="alert" announces on mount, so a server-rendered form with three errors would interrupt three times before the reader reached the first field. |
| value | string | '' | |
| id | string | — | |
| autoGrow | boolean | false | |
| valueChangeevent | EventEmitter<string> | — |
Emitted classes
Every framework emits the same classes — that is what makes the four libraries look identical. You can use them directly, without any component library.
| Class | Role | Notes |
|---|---|---|
| .aura-field-group | base | Required. A modifier does nothing without it. |
| .aura-label | base | Required. A modifier does nothing without it. |
| .aura-textarea | base | Required. A modifier does nothing without it. |
| .aura-textarea--autogrow | modifier |
Tokens and rules
components.css- min height
- var(--textarea-min-h)
- autogrow
- field-sizing: content
- padding
- var(--control-py) var(--control-px)
- frame
- var(--field-border) · var(--field-radius)
- focus
- var(--accent) · var(--focus-ring)