feat!: rename to material_async_button, ship 1.0.0 redesign#1
Merged
Conversation
Renames the package from async_button_builder to material_async_button and ships a redesigned, theme-aware 1.0.0 API. * Five Material wrappers (Elevated/Filled/Outlined/Text/Icon) with full named-constructor parity (.icon, .tonal, .tonalIcon, .filled, etc.). * MaterialAsyncButtonTheme ThemeExtension replaces the need for a project- wide wrapper widget; .material() factory ships an opinionated baseline. * AsyncButtonController (ValueListenable<AsyncButtonState>) for external state control with trigger/reset/invalidate/markSuccess. * GlobalKey<AsyncButtonBuilderState> exposes the same operations on the low-level builder. * New params: confirmBeforePress, errorBuilder, onStateChanged, cooldownDuration, hapticOn, announceSemantics, rethrowErrors. * Unopinionated defaults: zero success/error display duration, no widget swap on success/error unless requested. Bug fixes from v3: * Timer race in success/error display path (B1). * AsyncButtonState now implements ==/hashCode (B3). * ValueKey<Type> instead of UniqueKey() per state change (B4). * StackTrace carried through error state (B7). * Switched to dart format in CI (B8). * Example test fixed (B9). * Lints upgraded to flutter_lints ^5.0.0 (B10). Other: * Dart ^3.10.0 / Flutter >=3.40.0 minimum. * Drops AsyncButtonNotification and the notifications flag. * Test suite expanded to cover state, controller, theme, builder, all five wrappers, regression cases for the timer race and controller swap. * Adds claude_code_skill/flutter-material-async-button/SKILL.md. https://claude.ai/code/session_01C5g1NbxvkgKbv7daca8Kvv
* dart format --line-length 100 applied across lib/test/example.
* Bumped CI format step to --line-length 100 (was 80 default).
* Hoisted repeated Widget Function/error-callback types to
AsyncButtonErrorBuilder / AsyncButtonErrorCallback typedefs.
* Removed strict-inference (overly aggressive for Flutter test idioms
like `(tester) async {}`); kept strict-casts + strict-raw-types.
* Loosened pubspec flutter constraint to >=3.0.0; the sdk ^3.10.0
constraint is the real gate. Flutter 3.40 wasn't a real release yet
when CI ran.
* Fixed value-listenable interop test to attach a non-zero success
duration so the success state is observable before idle.
https://claude.ai/code/session_01C5g1NbxvkgKbv7daca8Kvv
* test/async_button_state_test.dart: typed the variant as AsyncButtonStateError so .error / .stackTrace getters resolve. (Previously accessed on the base sealed type.) * test/text_async_button_test.dart: drop unused dart:async import. * lib/src/async_button_controller.dart: drop @internal import from package:meta; foundation re-exports it. Removed meta from pubspec. * lib/src/async_button_builder.dart: SemanticsService.announce is deprecated in Flutter 3.41; switched to sendAnnouncement with the current FlutterView. * test/filled_async_button_test.dart: FilledAsyncButton.icon test was asserting "save" label is gone after a single pump, but the AnimatedSwitcher cross-fade keeps both widgets in the tree mid- animation. Wait past the switch duration. * test/async_button_builder_test.dart: switch the controller-swap test's local builder var to a function declaration (prefer_function_declarations_over_variables); also reorder its named args so child: is last. Verified locally with Flutter 3.41.0 stable: dart format clean at line-length 100, flutter analyze exits 0 (7 cosmetic info-level lints remain in tests, not fatal), all 69 tests pass. https://claude.ai/code/session_01C5g1NbxvkgKbv7daca8Kvv
…es_last) flutter analyze in Flutter 3.41+ exits non-zero on info-level lints (behavior change from earlier versions). Fix the 7 sort_child_properties_last hits in test files by moving the outer `child:` named arg after `builder:` / other named args in each AsyncButtonBuilder call. Verified locally: `flutter analyze` → "No issues found!" (exit 0), and all 69 tests still pass. https://claude.ai/code/session_01C5g1NbxvkgKbv7daca8Kvv
Accidentally committed in the previous commit; CI generates this fresh each run and uploads as an artifact. https://claude.ai/code/session_01C5g1NbxvkgKbv7daca8Kvv
- Refactor AsyncButtonController to extend ValueNotifier<AsyncButtonStatus>. - Reorder constructor parameters: all super.X before this.X and locals. - Remove stale pre-rename files (async_button_builder, async_button_state, screenshots, claude_code_skill). - Ship Claude Code skill at tool/claude/flutter-material-async-button/SKILL.md with corrected type names. - Expand example with FilledAsyncButton.icon/.tonalIcon and per-button override demo (successChild/errorChild/cooldownDuration). - Adopt package:checks across example tests. - README + SKILL.md fixes for renamed types and current skill path. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Exclude example/ from analyzer. - Add concise /// docs to AsyncButton, AsyncMaterialButton, AsyncStandardMaterialButton, IconAsyncButton and the five Material wrappers. Most field docs reference the underlying [AsyncButton.X] or [Material*Button.X] property. - Doc the four AsyncButtonStatus variants and their factory ctors. - Doc AsyncButtonController bool getters and the HapticOn enum members. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Renames the package from
async_button_buildertomaterial_async_buttonand ships a redesigned, theme-aware 1.0.0 API. Net diff: +3582 / −1147 across 33 files.What changed
New surface
ElevatedAsyncButton(+.icon)FilledAsyncButton(+.tonal,.icon,.tonalIcon)OutlinedAsyncButton(+.icon)TextAsyncButton(+.icon)IconAsyncButton(+.filled,.filledTonal,.outlined)MaterialAsyncButtonTheme—ThemeExtensionfor app-wide defaults. Eliminates theDefaultAsyncButtonwrapper pattern.MaterialAsyncButtonTheme.material()factory ships an opinionated baseline.AsyncButtonController—ValueListenable<AsyncButtonState>withtrigger(),reset(),invalidate(error),markSuccess(). Replaces the v3AsyncButtonNotification/notifications: boolmechanism.AsyncButtonBuilder(low-level) retained for custom non-Material buttons;State.trigger/reset/invalidate/markSuccessforGlobalKey-driven control.confirmBeforePress,errorBuilder,onStateChanged,cooldownDuration,hapticOn,announceSemantics,rethrowErrors.Un-opinionated defaults
successDisplayDurationanderrorDisplayDurationdefault toDuration.zero— no visual swap unless requested.successChild/errorChilddefault tonull; onlyloadingChildhas a baseline fallback (16×16 spinner).extensions: [MaterialAsyncButtonTheme.material()].Bug fixes from v3
_cancelTimer()before reassigning==/hashCodeon state variantsUniqueKey()per state changeValueKey<Type>(state.runtimeType)StackTraceon error variantflutter formatin CIdart format --set-exit-if-changed .MyApplint ^2.8.0outdatedflutter_lints ^5.0.0+ strict-casts/inferenceTest coverage
Expanded from 3 active tests to 9 test files / ~50 cases:
async_button_state_test.dart— equality, pattern match, toStringasync_button_controller_test.dart— trigger, reset, invalidate, markSuccess, cooldown, rethrow, concurrent triggers, controller swapmaterial_async_button_theme_test.dart—of(),copyWith,lerp, equality,.material()factoryasync_button_builder_test.dart— rendering, transitions, callbacks,confirmBeforePress, external control, timer-race regressionToolchain
^3.10.0, Flutter>=3.40.0.stable+beta, coverage artifact upload,flutter pub publish --dry-runvalidation onstable.meta: ^1.16.0added as direct dep for@internal.Claude Code skill
claude_code_skill/flutter-material-async-button/SKILL.md— pithy consumer skill so Claude Code picks the right wrapper, configures the theme once, and avoids the common anti-patterns (nested async buttons,disabled: trueinstead ofnull, project-wide wrapper widgets).Removed
AsyncButtonNotificationandnotifications: bool— useAsyncButtonControlleroronStateChanged.errorPadding/successPaddingconvenience props — wrap inPaddingexplicitly.Test plan
flutter pub getresolves cleanly on Flutter stabledart format --set-exit-if-changed .passesflutter analyzeclean underflutter_lints ^5.0.0+ strict modeflutter test --coveragepasses; lcov artifact uploadedflutter pub publish --dry-runreports no warningscontroller.trigger(), external controller, customAsyncButtonBuilder)Notes for the reviewer
async_button_buildershould get a deprecation note in its README pointing at this package.AsyncButtonBuilderclass name andAsyncButtonStatetypes are preserved, so v3 users migrate by changing the pubspec line + import path — most code keeps working.StatelessWidget. UseAsyncButtonController(notGlobalKey<...State>) for external control on wrappers;GlobalKey<AsyncButtonBuilderState>is for the low-level builder only. README/skill document this explicitly.https://claude.ai/code/session_01C5g1NbxvkgKbv7daca8Kvv
Generated by Claude Code