Skip to main content

loadable_buttons 1.0.1 copy "loadable_buttons: ^1.0.1" to clipboard
loadable_buttons: ^1.0.1 copied to clipboard

Provides enhanced buttons with built-in loading states, async functionality and customizable transitions.

loadable_buttons #

Flutter Material buttons with automatic loading states, external loading control, and customizable indicators and transitions.

Async Material button examples

Installation #

flutter pub add loadable_buttons

Requires Flutter 3.29.0+ and Dart 3.6.0+ (below 4.0.0). Version 1.x uses Flutter's Material library.

Quick start #

Paste this example into lib/main.dart in a Flutter application:

import 'package:flutter/material.dart';
import 'package:loadable_buttons/loadable_buttons.dart';

void main() {
  runApp(
    MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: Scaffold(
        body: Center(
          child: AsyncElevatedButton(
            onPressed: saveChanges,
            loadingSemanticsLabel: 'Saving',
            child: const Text('Save'),
          ),
        ),
      ),
    ),
  );
}

Future<void> saveChanges() async {
  // Replace this delay with your application's async operation.
  await Future<void>.delayed(const Duration(seconds: 2));
}

The button shows a spinner and prevents repeated activation until the returned Future completes. The following examples reuse saveChanges.

Button families #

Widget Constructors
AsyncElevatedButton Default, .icon
AsyncFilledButton Default, .icon, .tonal, .tonalIcon
AsyncOutlinedButton Default, .icon
AsyncTextButton Default, .icon
AsyncIconButton Default, .filled, .filledTonal, .outlined
AsyncFloatingActionButton Default, .small, .large, .extended

Use the corresponding Material options, such as style and focusNode. For each widget's supported properties, see the API reference.

For a button with an icon, use label instead of child:

AsyncFilledButton.icon(
  onPressed: saveChanges,
  icon: const Icon(Icons.save_outlined),
  label: const Text('Save changes'),
);

Loading behavior #

onPressed accepts synchronous or asynchronous callbacks. Return or await your async work so the button can track its completion.

External loading and a pending callback are independent: the button stays loading while either is active.

// isSaving is a bool managed by your application.
AsyncElevatedButton(
  loading: isSaving,
  onPressed: saveChanges,
  child: const Text('Save'),
);

Setting loading: false does not cancel or unlock a pending callback. Likewise, finishing the callback does not clear external loading: true.

Internal loading clears even if the callback throws. Exceptions are not swallowed; handle errors in your callback. Disposing the widget does not cancel the operation. Check mounted before updating your widget's state after an await.

Set onPressed: null to disable a button. Elevated, Filled, Outlined, and Text buttons remain enabled if onLongPress is provided; loading blocks both callbacks. onLongPress is synchronous and does not start a loading state.

Customization #

Replace the spinner with loadingChild and choose a transition:

AsyncElevatedButton(
  onPressed: saveChanges,
  loadingChild: const Text('Saving...'),
  transitionType: TransitionAnimationType.animatedSwitcher,
  animationDuration: const Duration(milliseconds: 250),
  child: const Text('Save'),
);
TransitionAnimationType Behavior
stack (default) Keeps idle content in the layout and fades loading content over it.
animatedSwitcher Fades between content with animated sizing.
customBuilder Uses your required customBuilder(loading, child, loadingChild).

animationDuration defaults to Durations.medium1; minimumChildOpacity defaults to 0.0 for stack transitions. Custom builders must handle a nullable loadingChild and manage outgoing content, interaction, and semantics.

Constrain loading content if you need a stable button size, and give custom indicators appropriate semantics. AsyncElevatedButton supports loadingSemanticsLabel for its default spinner.

IconButton selection #

With a Material 3 theme, use isSelected and selectedIcon on any AsyncIconButton variant. Wrap a bool in WidgetStatePropertyAll:

// In a State object's build method; isFavorite is a bool field.
AsyncIconButton.filled(
  tooltip: 'Toggle favorite',
  isSelected: WidgetStatePropertyAll(isFavorite),
  icon: const Icon(Icons.favorite_border),
  selectedIcon: const Icon(Icons.favorite),
  onPressed: () async {
    await saveChanges();
    if (!mounted) return;
    setState(() => isFavorite = !isFavorite);
  },
);

Your application owns the selection state. If selectedIcon is omitted, icon is used for both states.

FAQ #

Can I copy a button into my project?

Yes! The code is MIT licensed. Feel free to browse the button implementations, copy a button into your project, and adapt it, including for commercial use. Keep the copyright and MIT license notice with the copied code.

Include any companion part files and referenced types, and update package imports to match your project.

Do I need a controller or state management package?

No. Return your operation's Future from onPressed and the button manages its loading state. Use loading when your application already manages that state.

More #

16
likes
0
points
425
downloads

Publisher

unverified uploader

Weekly Downloads

Provides enhanced buttons with built-in loading states, async functionality and customizable transitions.

Homepage
Repository (GitHub)
View/report issues

Topics

#button #loading #material #ui #widget

License

unknown (license)

Dependencies

flutter

More

Packages that depend on loadable_buttons