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.
NameTypeDefaultNotes
labelstring
hintstringStanding help under the control, always shown.
errorstringWhat 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.
valuestring
defaultValuestring
onValueChange(value: string) => void
idstringThe generated id comes from the framework itself, so it is stable across SSR and hydration.
autoGrowbooleanfalseGrows 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.
inputClassNamestring
NameTypeDefaultNotes
labelstring
hintstringStanding help under the control, always shown.
errorstringWhat 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-waystring
defaultValuestring
idstringThe generated id comes from the framework itself, so it is stable across SSR and hydration.
autoGrowbooleanfalse
update:modelValueevent(value: string) => void
NameTypeDefaultNotes
labelstring
hintstringStanding help under the control, always shown.
errorstringWhat 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-waystring''
idstringThe generated id comes from the framework itself, so it is stable across SSR and hydration.
autoGrowbooleanfalse
NameTypeDefaultNotes
labelstring
hintstringStanding help under the control, always shown.
errorstringWhat 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.
valuestring''
idstring
autoGrowbooleanfalse
valueChangeeventEventEmitter<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.

ClassRoleNotes
.aura-field-groupbaseRequired. A modifier does nothing without it.
.aura-labelbaseRequired. A modifier does nothing without it.
.aura-textareabaseRequired. A modifier does nothing without it.
.aura-textarea--autogrowmodifier

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)