state_button
An animated Flutter button that transitions through idle โ loading โ success / failure โ idle with zero boilerplate.
Features
- ๐ฏ Four phases:
idle,loading,success,failure - โจ Animated tick (โ) and cross (โ) drawn with
CustomPainter - ๐ Tap-lock during loading โ no double-submission guard needed
- ๐ Auto-resets to idle after success or failure
- ๐จ Fully customisable: colours, radius, shadow, size, duration
- ๐ฆ Zero external dependencies beyond Flutter itself
Installation
Run this command:
flutter pub add state_button
Or add manually to pubspec.yaml:
dependencies:
state_button: ^latest-version
Then run flutter pub get and import:
import 'package:state_button/state_button.dart';
Previews
1 ยท Primary filled button
Solid indigo fill, white label. Demonstrates a failure flow.
StateButton(
controller: _ctrl,
width: double.infinity,
onPressed: () async {
_ctrl.setLoading();
await Future.delayed(const Duration(seconds: 2));
_ctrl.setFailure();
},
child: const Text(
'Submit',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w600,
fontSize: 16,
),
),
)
2 ยท Outlined / custom decoration button
White background with a coloured border. Success and failure icons use matching brand colours instead of white.
StateButton(
controller: _ctrl,
width: double.infinity,
backgroundColor: Colors.white,
successColor: const Color(0xFF22C55E),
failureColor: const Color(0xFFEF4444),
successIconColor: const Color(0xFF22C55E),
failureIconColor: const Color(0xFFEF4444),
loadingColor: const Color(0xFF6366F1),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
border: Border.all(color: const Color(0xFF6366F1), width: 1.5),
),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.06),
blurRadius: 8,
offset: const Offset(0, 3),
),
],
onPressed: () async {
_ctrl.setLoading();
await Future.delayed(const Duration(seconds: 2));
_ctrl.setSuccess();
},
child: const Text(
'Upload File',
style: TextStyle(color: Color(0xFF6366F1), fontSize: 15),
),
)
3 ยท Button with icon + label
Fully rounded pill shape with a dark background and an icon-label row child. Demonstrates a success flow with a custom
autoResetDuration.
StateButton(
controller: _ctrl,
borderRadius: 999,
padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 14),
backgroundColor: const Color(0xFF0F172A),
autoResetDuration: const Duration(seconds: 2),
boxShadow: [
BoxShadow(
color: const Color(0xFF0F172A).withValues(alpha: 0.35),
blurRadius: 16,
offset: const Offset(0, 6),
),
],
onPressed: () async {
_ctrl.setLoading();
await Future.delayed(const Duration(milliseconds: 1500));
_ctrl.setSuccess();
},
child: const Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.rocket_launch_rounded, color: Colors.white, size: 18),
SizedBox(width: 8),
Text(
'Deploy',
style: TextStyle(color: Colors.white, fontSize: 15),
),
],
),
)
API Reference
SbController
| Member | Type | Description |
|---|---|---|
phase |
SbPhase |
Current phase (read-only) |
setIdle() |
void |
Reset to tappable idle state |
setLoading() |
void |
Show spinner, block taps |
setSuccess() |
void |
Show animated โ, then auto-reset |
setFailure() |
void |
Show animated โ, then auto-reset |
dispose() |
void |
Release resources โ call in dispose() |
SbPhase
enum SbPhase { idle, loading, success, failure }
StateButton parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
controller |
SbController |
required | Drives phase transitions |
onPressed |
VoidCallback |
required | Called on tap (idle phase only) |
child |
Widget |
Text('Submit') |
Widget shown in idle phase |
width |
double? |
null |
Fixed width; null = stretch |
height |
double |
52 |
Fixed height in logical pixels |
padding |
EdgeInsetsGeometry |
h:24 v:12 |
Inner padding |
margin |
EdgeInsetsGeometry |
zero |
Outer margin |
borderRadius |
double |
12 |
Corner radius; use 999 for pill |
backgroundColor |
Color |
#6366F1 |
Fill colour in idle phase |
successColor |
Color |
#22C55E |
Fill colour in success phase |
failureColor |
Color |
#EF4444 |
Fill colour in failure phase |
splashColor |
Color? |
white 15% | Ink splash on tap |
highlightColor |
Color? |
white 8% | Ink highlight on long-press |
decoration |
BoxDecoration? |
null |
Overrides all container decoration |
boxShadow |
List<BoxShadow>? |
null |
Drop shadows (ignored if decoration set) |
indicatorSize |
double |
26 |
Diameter of spinner / tick / cross |
loadingColor |
Color |
white |
Spinner colour |
successIconColor |
Color |
white |
Tick + circle stroke colour |
failureIconColor |
Color |
white |
Cross + circle stroke colour |
autoResetDuration |
Duration |
1 800 ms |
Time before auto-reset to idle |
animationDuration |
Duration |
300 ms |
Colour fade + content crossfade speed |
โ Support
๐ Connect
Libraries
- A lightweight Flutter package that provides an animated button capable of expressing four visual states: idle, loading, success, and failure.