loading_icon_button

pub package GitHub Stars GitHub Issues GitHub License X

A comprehensive Flutter package providing customizable loading buttons with icons, text, and smooth animations. Features multiple button types including LoadingButton, AutoLoadingButton, and ArgonButton with Material Design compliance.

Features

  • Multiple Button Types: LoadingButton, AutoLoadingButton, and ArgonButton
  • Material Design: Full Material Design compliance with Material 3 support
  • Customizable States: Idle, Loading, Success, Error states with smooth transitions
  • Icon Support: Built-in icon support with customizable icons for each state
  • Cross-Platform: Works on Android, iOS, Linux, macOS, web, and Windows
  • Accessible: Full accessibility support with semantic labels
  • Responsive: Automatic responsive design for tablets and mobile devices
  • Zero Boilerplate: Easy to use with minimal configuration
  • Customizable Animations: Configurable animation durations and effects

Installation

Add this to your pubspec.yaml file:

dependencies:
  loading_icon_button: ^latest

Then run:

flutter pub get

Quick Start

Import

import 'package:loading_icon_button/loading_icon_button.dart';

Basic Usage

LoadingButton(
  child: const Text('Login with Apple'),
  iconData: Icons.apple,
  onPressed: () => _handleLogin(),
)

Button Types

1. LoadingButton

The main button with full customization options:

LoadingButton(
  child: const Text('Submit'),
  iconData: Icons.send,
  onPressed: () async {
    // Your async operation
    await Future.delayed(Duration(seconds: 2));
  },
  duration: Duration(milliseconds: 300),
  successColor: Colors.green,
  errorColor: Colors.red,
  successIcon: Icons.check,
  failedIcon: Icons.error,
)

2. AutoLoadingButton (Material Design)

A Material Design compliant button with automatic loading states:

ElevatedAutoLoadingButton(
  onPressed: () async {
    // Automatically shows loading state
    await _performOperation();
    // Automatically shows success/error state
  },
  child: const Text('Auto Loading'),
  style: ButtonStyle(
    backgroundColor: WidgetStateProperty.all(Colors.blue),
    foregroundColor: WidgetStateProperty.all(Colors.white),
    borderRadius: WidgetStateProperty.all(BorderRadius.circular(8.0)),
  ),
)

3. LoadingButton

Enhanced Material Design button with advanced features:

LoadingButton(
  type: ButtonType.elevated,
  onPressed: () => _simulateLogin(),
  child: const Row(
    mainAxisSize: MainAxisSize.min,
    children: [
      Icon(Icons.login),
      SizedBox(width: 8),
      Text('Login'),
    ],
  ),
  style: const LoadingButtonStyle(
    backgroundColor: Colors.blue,
    foregroundColor: Colors.white,
    borderRadius: 8,
  ),
  loadingText: 'Logging in...',
  successText: 'Welcome!',
  errorText: 'Login failed',
  onError: (error) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Text('Login error: $error'),
        backgroundColor: Colors.red,
      ),
    );
  },
),

4. ArgonButton

A specialized button with advanced loader customization:

ArgonButton(
  height: 50,
  width: 350,
  borderRadius: 5.0,
  color: Color(0xFF7866FE),
  child: Text(
    "Continue",
    style: TextStyle(
      color: Colors.white,
      fontSize: 18,
      fontWeight: FontWeight.w700,
    ),
  ),
  loader: Container(
    padding: EdgeInsets.all(10),
    child: CircularProgressIndicator(
      color: Colors.white,
    ),
  ),
  onTap: (startLoading, stopLoading, btnState) {
    if (btnState == ButtonState.Idle) {
      startLoading();
      // Perform your operation
      doNetworkRequest().then((_) {
        stopLoading();
      });
    }
  },
)

Use the fluent builder pattern for cleaner code:

LoadingButtonBuilder.elevated()
  .onPressed(_handleSubmit)
  .child(Text('Submit'))
  .loadingText('Processing...')
  .successText('Done!')
  .errorText('Failed!')
  .style(LoadingButtonStyle(
    backgroundColor: Colors.blue,
    borderRadius: 25,
  ))
  .build()

Properties

LoadingButton Properties

Property Type Default Description
child Widget required The widget to display when button is idle
iconData IconData? null Icon to display alongside text
onPressed VoidCallback? null Callback when button is pressed
duration Duration 300ms Animation duration
loaderSize double 20.0 Size of the loading indicator
animateOnTap bool true Whether to animate on tap
resetAfterDuration bool true Auto-reset after success/error
errorColor Color? Colors.red Color for error state
successColor Color? Colors.green Color for success state
successIcon IconData? Icons.check Icon for success state
failedIcon IconData? Icons.error Icon for error state
iconColor Color? null Color for icons
showBox bool true Whether to show button container

AutoLoadingButton Properties

Property Type Default Description
onPressed VoidCallback? null Async callback function
child Widget required Button content
style ButtonStyle? null Button styling

ArgonButton Properties

Property Type Default Description
height double 50.0 Button height
width double 350.0 Button width
borderRadius double 5.0 Border radius
color Color Colors.blue Button background color
child Widget required Button content
loader Widget? null Custom loader widget
onTap Function(Function, Function, ButtonState) required Tap callback with state control

Examples

Basic Login Button

class LoginScreen extends StatefulWidget {
  @override
  _LoginScreenState createState() => _LoginScreenState();
}

class _LoginScreenState extends State {

  void _handleLogin() async {
    try {
      // Simulate login process
      await Future.delayed(Duration(seconds: 2));

      // Simulate random success/failure
      if (DateTime.now().millisecondsSinceEpoch % 2 == 0) {
        throw Exception('Login failed');
      }
    } catch (e) {
      throw Exception('Login failed');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: LoadingButton(
          onPressed: _handleLogin,
          child: Text('Login'),
          iconData: Icons.login,
          successIcon: Icons.check_circle,
          failedIcon: Icons.error_outline,
        ),
      ),
    );
  }
}

File Upload with Progress

class FileUploadButton extends StatelessWidget {

  Future _uploadFile() async {
    _isLoading = true;
    // Simulate file upload
    await Future.delayed(Duration(seconds: 3));

    // Simulate random success/failure
    if (Random().nextBool()) {
      throw Exception('Upload failed');
    }
  }

  @override
  Widget build(BuildContext context) {
    return LoadingButton(
      onPressed: _uploadFile,
      child: Row(
        mainAxisSize: MainAxisSize.min,
        children: [
          Icon(Icons.cloud_upload),
          SizedBox(width: 8),
          Text('Upload File'),
        ],
      ),
    );
  }
}

Custom Styled Button

LoadingButtonBuilder.filled()
  .onPressed(_handleSubmit)
  .child(Text('Custom Button'))
  .style(LoadingButtonStyle(
    backgroundColor: Colors.deepPurple,
    foregroundColor: Colors.white,
    loadingBackgroundColor: Colors.deepPurple.shade300,
    successBackgroundColor: Colors.green,
    errorBackgroundColor: Colors.red,
    borderRadius: 30,
    elevation: 8,
    padding: EdgeInsets.symmetric(horizontal: 32, vertical: 16),
  ))
  .loadingText('Processing...')
  .successText('Success!')
  .errorText('Try Again')
  .build()

Global Configuration

Set global defaults for all buttons:

void main() {
  // Configure global settings
  LoadingButtonConfig().defaultAnimationDuration = Duration(milliseconds: 400);
  LoadingButtonConfig().enableHapticFeedback = true;
  LoadingButtonConfig().defaultLoadingWidget = MyCustomSpinner();

  runApp(MyApp());
}

Accessibility

The package includes full accessibility support:

  • Semantic Labels: Automatic screen reader support
  • Focus Management: Proper keyboard navigation
  • State Announcements: Screen reader announces state changes
  • High Contrast: Supports high contrast mode
LoadingButton(
  onPressed: _handleSubmit,
  child: Text('Submit'),
  // Accessibility labels
  loadingText: 'Processing your request',
  successText: 'Request completed successfully',
  errorText: 'Request failed, please try again',
)

Migration Guide

From v0.0.X to v1.0.X

  • Update import statements
  • Replace deprecated properties with new equivalents
  • Use LoadingButtonStyle for styling instead of individual properties

See the Migration Guide for detailed instructions.

Platform Support

Platform Support
Android
iOS
Linux
macOS
Web
Windows

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Development Setup

  1. Clone the repository
  2. Run flutter pub get
  3. Run flutter test to ensure tests pass
  4. Make your changes
  5. Add tests for new features
  6. Submit a pull request

Issues and Feedback

Please file issues and feedback on the GitHub Issues page.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgments

Special thanks to the Flutter community and contributors who made this package possible.

Package: loading_icon_button
Repository: GitHub
Issues: Report Issues