Components
Button
Clickable button with HeroUI v3 variants, sizes, icons, loading, and full width — aligned with @heroui/react and button.css (rounded-3xl, gap-2, press scale 0.97).
Usage
Basic `onPress` / `onPressed` handler.
RiseButton(
label: 'Click me',
onPressed: () {},
)Variants
Primary, secondary, tertiary, outline, ghost, danger, danger soft.
Wrap(
spacing: 12,
runSpacing: 12,
children: [
RiseButton(label: 'Primary', onPressed: () {}),
RiseButton(variant: RiseButtonVariant.secondary, label: 'Secondary', onPressed: () {}),
RiseButton(variant: RiseButtonVariant.tertiary, label: 'Tertiary', onPressed: () {}),
RiseButton(variant: RiseButtonVariant.outline, label: 'Outline', onPressed: () {}),
RiseButton(variant: RiseButtonVariant.ghost, label: 'Ghost', onPressed: () {}),
RiseButton(variant: RiseButtonVariant.danger, label: 'Danger', onPressed: () {}),
RiseButton(variant: RiseButtonVariant.dangerSoft, label: 'Danger soft', onPressed: () {}),
],
)With icons
Leading icon + label in a row.
RiseButton(
onPressed: () {},
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.search, size: 18),
SizedBox(width: 8),
Text('Search'),
],
),
)Icon only
`isIconOnly: true` — square hit target.
RiseButton(
isIconOnly: true,
onPressed: () {},
child: Icon(Icons.more_horiz),
)Loading
Spinner + label while pending (disabled tap).
RiseButton(
isDisabled: true,
onPressed: null,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(
width: 16,
height: 16,
child: CircularProgressIndicator(strokeWidth: 2, color: accentForeground),
),
SizedBox(width: 10),
Text('Uploading…'),
],
),
)Loading state
Outline button with leading icon (upload).
RiseButton(
variant: RiseButtonVariant.outline,
onPressed: () {},
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.attach_file, size: 18),
SizedBox(width: 8),
Text('Upload File'),
],
),
)Sizes
`sm` · `md` · `lg` — heights 32 / 40 / 44.
Row(
mainAxisSize: MainAxisSize.min,
children: [
RiseButton(size: RiseButtonSize.sm, label: 'Small', onPressed: () {}),
SizedBox(width: 16),
RiseButton(size: RiseButtonSize.md, label: 'Medium', onPressed: () {}),
SizedBox(width: 16),
RiseButton(size: RiseButtonSize.lg, label: 'Large', onPressed: () {}),
],
)Full width
`fullWidth: true`.
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
RiseButton(fullWidth: true, label: 'Primary Button', onPressed: () {}),
RiseButton(
fullWidth: true,
variant: RiseButtonVariant.outline,
onPressed: () {},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [Icon(Icons.add, size: 18), SizedBox(width: 8), Text('With Icon')],
),
),
],
)Disabled
`isDisabled: true` across variants.
RiseButton(
isDisabled: true,
label: 'Primary',
onPressed: () {},
)Social buttons
Outline + `fullWidth` stacked rows (swap icons for brand assets — no separate social primitive).
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
RiseButton(
fullWidth: true,
variant: RiseButtonVariant.outline,
onPressed: () {},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.g_mobiledata, size: 20),
SizedBox(width: 10),
Text('Sign in with Google'),
],
),
),
SizedBox(height: 12),
RiseButton(
fullWidth: true,
variant: RiseButtonVariant.outline,
onPressed: () {},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.code, size: 20),
SizedBox(width: 10),
Text('Sign in with GitHub'),
],
),
),
SizedBox(height: 12),
RiseButton(
fullWidth: true,
variant: RiseButtonVariant.outline,
onPressed: () {},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.apple, size: 20),
SizedBox(width: 10),
Text('Sign in with Apple'),
],
),
),
],
)Compound label
Compose `child` with `RiseButtonLabel` for variant-colored text (e.g. icon + label + muted suffix).
RiseButton(
variant: RiseButtonVariant.secondary,
onPressed: () {},
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.mail_outlined, size: 18),
SizedBox(width: 8),
RiseButtonLabel('Messages'),
SizedBox(width: 6),
Text(
'12',
style: Theme.of(context).textTheme.labelSmall?.copyWith(
color: context.riseTheme.mutedForeground(0.85),
),
),
],
),
)