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.tsInvalid
`[data-invalid]` + error text.
// Missing code for slug "invalid" in showcase-code-maps.ts