RiseUI
Components

TextArea

HeroUI-aligned multiline field — textarea.tsx, textarea.css (`rounded-field`, 38px min height, primary/secondary).

Usage

Story `Default`: placeholder, rows, maxLines.

const RiseTextArea(
  fullWidth: true,
  placeholder: 'Type your message…',
  rows: 3,
  maxLines: 8,
)

Controlled

Character count with `maxLength` (like a capped message).

Column(
  crossAxisAlignment: CrossAxisAlignment.start,
  children: [
    RiseTextArea(
      fullWidth: true,
      controller: controller,
      rows: 3,
      maxLines: 6,
      maxLength: 280,
      onChanged: (_) => setState(() {}),
    ),
    Text('Characters: ${controller.text.length} / 280'),
  ],
)

Rows

Different `rows` / `minLines` for short vs tall fields.

const Column(
  crossAxisAlignment: CrossAxisAlignment.start,
  children: [
    RiseTextArea(
      fullWidth: true,
      labelText: 'Short feedback',
      hintText: 'A few lines…',
      rows: 2,
      maxLines: 4,
    ),
    RiseTextArea(
      fullWidth: true,
      labelText: 'Detailed notes',
      rows: 5,
      maxLines: 10,
    ),
  ],
)

Full width

`.textarea--full-width` — stretch to container.

const RiseTextArea(
  fullWidth: true,
  placeholder: 'Full width textarea',
  rows: 4,
  maxLines: 8,
)

Variants

`Variants`: primary (`shadow-field`) vs secondary (`shadow-none`).

const Column(
  crossAxisAlignment: CrossAxisAlignment.start,
  children: [
    RiseTextArea(
      fullWidth: true,
      variant: RiseTextAreaVariant.primary,
      placeholder: 'Primary — shadow-field',
      rows: 3,
      maxLines: 6,
    ),
    RiseTextArea(
      fullWidth: true,
      variant: RiseTextAreaVariant.secondary,
      placeholder: 'Secondary — shadow-none',
      rows: 3,
      maxLines: 6,
    ),
  ],
)

Disabled

`[data-disabled]` / non-interactive.

// Missing code for slug "disabled" in showcase-code-maps.ts

Invalid

`[data-invalid]` + error text.

// Missing code for slug "invalid" in showcase-code-maps.ts