From 0f9a5c2f757b03b21606503042f2a6086728c035 Mon Sep 17 00:00:00 2001 From: PouriaMoradi021 Date: Wed, 15 Jan 2025 21:17:12 +0330 Subject: [PATCH 1/6] feat: add `AdaptivePrimaryButton` components - add a temporary sample button components with fluent-ui widget by using `FilledButton` - add a temporary sample use-case for this widget - update `main` file & add `FluentApp` to `themeBuilder` section so that we can use fluent-ui widgets - update `main.directories.dart` --- lib/main.dart | 13 +- lib/main.directories.g.dart | 47 ++++- .../adaptive_primary_button.dart | 48 +++++ .../adaptive_primary_button_usecase.dart | 31 +++ pubspec.lock | 190 +++++++++--------- 5 files changed, 222 insertions(+), 107 deletions(-) create mode 100644 lib/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button.dart create mode 100644 lib/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button_usecase.dart diff --git a/lib/main.dart b/lib/main.dart index 5cf89e1..d1ecdfc 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,11 +1,9 @@ import 'package:fluent_ui/fluent_ui.dart'; -import 'package:flutter/material.dart'; import 'package:pactus_gui_widgetbook/app_scaffold.dart'; import 'package:pactus_gui_widgetbook/src/core/theme/app_theme.dart'; import 'package:pactus_gui_widgetbook/src/core/theme/app_theme_data.dart'; import 'package:widgetbook/widgetbook.dart'; import 'package:widgetbook_annotation/widgetbook_annotation.dart' as widgetbook; -import 'package:flutter/widgets.dart'; import 'package:pactus_gui_widgetbook/src/core/utils/gen/localization/app_locales.dart'; import 'package:pactus_gui_widgetbook/src/core/utils/gen/localization/customized_localization_addon.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; @@ -99,9 +97,14 @@ class WidgetBookApp extends StatelessWidget { ) ], themeBuilder: (context, data, child) { - return AppTheme( - themeData: data, - child: AppScaffold(child: child), + return FluentApp( + debugShowCheckedModeBanner: false, + theme: data, + themeMode: ThemeMode.light, + home: AppTheme( + themeData: data, + child: AppScaffold(child: child), + ), ); }, ), diff --git a/lib/main.directories.g.dart b/lib/main.directories.g.dart index 27ef23e..6054c62 100644 --- a/lib/main.directories.g.dart +++ b/lib/main.directories.g.dart @@ -9,10 +9,14 @@ // ************************************************************************** // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'package:pactus_gui_widgetbook/src/features/widgets/counter/counter_usecase.dart' +import 'package:pactus_gui_widgetbook/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button_usecase.dart' as _i2; -import 'package:pactus_gui_widgetbook/src/features/widgets/custom_button/custom_button_usecase.dart' +import 'package:pactus_gui_widgetbook/src/features/widgets/counter/counter_usecase.dart' as _i3; +import 'package:pactus_gui_widgetbook/src/features/widgets/custom_button/custom_button_usecase.dart' + as _i4; +import 'package:pactus_gui_widgetbook/src/features/widgets/custom_text/custom_text_usecase.dart' + as _i5; import 'package:widgetbook/widgetbook.dart' as _i1; final directories = <_i1.WidgetbookNode>[ @@ -22,6 +26,35 @@ final directories = <_i1.WidgetbookNode>[ _i1.WidgetbookFolder( name: 'widgets', children: [ + _i1.WidgetbookFolder( + name: 'buttons', + children: [ + _i1.WidgetbookFolder( + name: 'adaptive_primary_button', + children: [ + _i1.WidgetbookLeafComponent( + name: 'AdaptivePrimaryButton', + useCase: _i1.WidgetbookUseCase( + name: 'Fluent Button with Knobs', + builder: _i2.fluentButtonUseCase, + ), + ) + ], + ) + ], + ), + _i1.WidgetbookFolder( + name: 'counter', + children: [ + _i1.WidgetbookLeafComponent( + name: 'CounterWidget', + useCase: _i1.WidgetbookUseCase( + name: 'Counter with Knobs', + builder: _i3.counterWidgetUseCase, + ), + ) + ], + ), _i1.WidgetbookFolder( name: 'custom_button', children: [ @@ -29,19 +62,19 @@ final directories = <_i1.WidgetbookNode>[ name: 'CustomButtonWidget', useCase: _i1.WidgetbookUseCase( name: 'Custom Button with Knobs', - builder: _i3.customButtonWidgetUseCase, + builder: _i4.customButtonWidgetUseCase, ), ) ], ), _i1.WidgetbookFolder( - name: 'counter', + name: 'custom_text', children: [ _i1.WidgetbookLeafComponent( - name: 'CounterWidget', + name: 'CustomTextWidget', useCase: _i1.WidgetbookUseCase( - name: 'Counter with Knobs', - builder: _i2.counterWidgetUseCase, + name: 'Select the text to display from the dropdown', + builder: _i5.customTextWidgetUseCase, ), ) ], diff --git a/lib/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button.dart b/lib/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button.dart new file mode 100644 index 0000000..88e923e --- /dev/null +++ b/lib/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button.dart @@ -0,0 +1,48 @@ +import 'package:fluent_ui/fluent_ui.dart'; + +class AdaptivePrimaryButton extends StatelessWidget { + const AdaptivePrimaryButton( + {super.key, required this.text, this.onPressed, required this.disabled}); + final String text; + final VoidCallback? onPressed; + final bool disabled; + @override + Widget build(BuildContext context) { + return FilledButton( + onPressed: disabled ? null : onPressed, + style: ButtonStyle( + backgroundColor: WidgetStateProperty.resolveWith((states) { + if (states.contains(WidgetState.disabled)) { + return Colors.grey[100]; + } else if (states.contains(WidgetState.pressed)) { + return Colors.blue.darker; + } else if (states.contains(WidgetState.hovered)) { + return Colors.blue.dark; + } + return Colors.blue; + }), + foregroundColor: WidgetStateProperty.resolveWith((states) { + if (states.contains(WidgetState.disabled)) { + return Colors.grey[120]; + } + return Colors.white; + }), + shape: WidgetStateProperty.resolveWith((states) { + return RoundedRectangleBorder( + side: BorderSide( + color: states.contains(WidgetState.disabled) + ? Colors.grey[130] + : Colors.blue.darker, + width: 2, + ), + borderRadius: BorderRadius.circular(8), + ); + }), + ), + child: Text( + text, + style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600), + ), + ); + } +} diff --git a/lib/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button_usecase.dart b/lib/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button_usecase.dart new file mode 100644 index 0000000..f708a4a --- /dev/null +++ b/lib/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button_usecase.dart @@ -0,0 +1,31 @@ +import 'package:fluent_ui/fluent_ui.dart'; +import 'package:pactus_gui_widgetbook/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button.dart'; +import 'package:widgetbook/widgetbook.dart'; +import 'package:widgetbook_annotation/widgetbook_annotation.dart'; + +@UseCase(name: 'Fluent Button with Knobs', type: AdaptivePrimaryButton) +Widget fluentButtonUseCase(BuildContext context) { + final text = context.knobs.string( + label: 'Button Text', + initialValue: 'Click Me', + description: 'Set the text displayed on the button.', + ); + + final isDisabled = context.knobs.boolean( + label: 'Disabled', + initialValue: false, + description: 'Enable or disable the button.', + ); + + return Center( + child: AdaptivePrimaryButton( + text: text, + disabled: isDisabled, + onPressed: isDisabled + ? null + : () { + debugPrint('Button Pressed'); + }, + ), + ); +} diff --git a/pubspec.lock b/pubspec.lock index f048c40..7bf7c13 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -6,7 +6,7 @@ packages: description: name: _fe_analyzer_shared sha256: f256b0c0ba6c7577c15e2e4e114755640a875e885099367bf6e012b19314c834 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "72.0.0" _macros: @@ -19,7 +19,7 @@ packages: description: name: accessibility_tools sha256: b49df78d786610d642f16787a84da737bcc4dd18533a9cb41cb35eb5ceee5e4c - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.3.0" analyzer: @@ -27,7 +27,7 @@ packages: description: name: analyzer sha256: b652861553cd3990d8ed361f7979dc6d7053a9ac8843fa73820ab68ce5410139 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "6.7.0" args: @@ -35,7 +35,7 @@ packages: description: name: args sha256: bf9f5caeea8d8fe6721a9c358dd8a5c1947b27f1cfaa18b39c301273594919e6 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.6.0" async: @@ -43,7 +43,7 @@ packages: description: name: async sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.11.0" boolean_selector: @@ -51,7 +51,7 @@ packages: description: name: boolean_selector sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.1" build: @@ -59,7 +59,7 @@ packages: description: name: build sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.4.1" build_config: @@ -67,7 +67,7 @@ packages: description: name: build_config sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.1.1" build_daemon: @@ -75,7 +75,7 @@ packages: description: name: build_daemon sha256: "79b2aef6ac2ed00046867ed354c88778c9c0f029df8a20fe10b5436826721ef9" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.0.2" build_resolvers: @@ -83,7 +83,7 @@ packages: description: name: build_resolvers sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.4.2" build_runner: @@ -91,7 +91,7 @@ packages: description: name: build_runner sha256: "028819cfb90051c6b5440c7e574d1896f8037e3c96cf17aaeb054c9311cfbf4d" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.4.13" build_runner_core: @@ -99,7 +99,7 @@ packages: description: name: build_runner_core sha256: f8126682b87a7282a339b871298cc12009cb67109cfa1614d6436fb0289193e0 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "7.3.2" built_collection: @@ -107,7 +107,7 @@ packages: description: name: built_collection sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "5.1.1" built_value: @@ -115,7 +115,7 @@ packages: description: name: built_value sha256: "28a712df2576b63c6c005c465989a348604960c0958d28be5303ba9baa841ac2" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "8.9.3" characters: @@ -123,7 +123,7 @@ packages: description: name: characters sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.3.0" checked_yaml: @@ -131,7 +131,7 @@ packages: description: name: checked_yaml sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.0.3" clock: @@ -139,7 +139,7 @@ packages: description: name: clock sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.1.1" code_builder: @@ -147,7 +147,7 @@ packages: description: name: code_builder sha256: "0ec10bf4a89e4c613960bf1e8b42c64127021740fb21640c29c909826a5eea3e" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.10.1" collection: @@ -155,7 +155,7 @@ packages: description: name: collection sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.18.0" color: @@ -163,7 +163,7 @@ packages: description: name: color sha256: ddcdf1b3badd7008233f5acffaf20ca9f5dc2cd0172b75f68f24526a5f5725cb - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.0.0" convert: @@ -171,7 +171,7 @@ packages: description: name: convert sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.1.2" crypto: @@ -179,7 +179,7 @@ packages: description: name: crypto sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.0.6" cupertino_icons: @@ -187,7 +187,7 @@ packages: description: name: cupertino_icons sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.0.8" dart_style: @@ -195,7 +195,7 @@ packages: description: name: dart_style sha256: "7856d364b589d1f08986e140938578ed36ed948581fbc3bc9aef1805039ac5ab" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.3.7" dartx: @@ -203,7 +203,7 @@ packages: description: name: dartx sha256: "8b25435617027257d43e6508b5fe061012880ddfdaa75a71d607c3de2a13d244" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.2.0" device_frame: @@ -211,7 +211,7 @@ packages: description: name: device_frame sha256: d031a06f5d6f4750009672db98a5aa1536aa4a231713852469ce394779a23d75 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.2.0" fake_async: @@ -219,7 +219,7 @@ packages: description: name: fake_async sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.3.1" file: @@ -227,7 +227,7 @@ packages: description: name: file sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "7.0.1" fixnum: @@ -235,7 +235,7 @@ packages: description: name: fixnum sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.1.1" fluent_ui: @@ -243,7 +243,7 @@ packages: description: name: fluent_ui sha256: e7804bf3bbb3ecf9e77d5498181dc36375f5ca736ccfb3862fea17c50050eb89 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.9.2" flutter: @@ -256,7 +256,7 @@ packages: description: name: flutter_gen_core sha256: "46ecf0e317413dd065547887c43f93f55e9653e83eb98dc13dd07d40dd225325" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "5.8.0" flutter_gen_runner: @@ -264,7 +264,7 @@ packages: description: name: flutter_gen_runner sha256: "77f0a02fc30d9fcf2549fe874eb3fde091435724904bcbb1af60aa40cbfab1f4" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "5.8.0" flutter_lints: @@ -272,7 +272,7 @@ packages: description: name: flutter_lints sha256: "3f41d009ba7172d5ff9be5f6e6e6abb4300e263aab8866d2a0842ed2a70f8f0c" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.0.0" flutter_localizations: @@ -290,7 +290,7 @@ packages: description: name: freezed_annotation sha256: c2e2d632dd9b8a2b7751117abcfc2b4888ecfe181bd9fca7170d9ef02e595fe2 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.4.4" frontend_server_client: @@ -298,7 +298,7 @@ packages: description: name: frontend_server_client sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.0.0" glob: @@ -306,7 +306,7 @@ packages: description: name: glob sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.2" graphs: @@ -314,7 +314,7 @@ packages: description: name: graphs sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.3.2" hashcodes: @@ -322,7 +322,7 @@ packages: description: name: hashcodes sha256: "80f9410a5b3c8e110c4b7604546034749259f5d6dcca63e0d3c17c9258f1a651" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.0.0" http_multi_server: @@ -330,7 +330,7 @@ packages: description: name: http_multi_server sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.2.2" http_parser: @@ -338,7 +338,7 @@ packages: description: name: http_parser sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.0.2" image_size_getter: @@ -346,7 +346,7 @@ packages: description: name: image_size_getter sha256: c3900f04e31468a81aa23b09b1c7d09c3c952122bbe9ecdae336977b7be24c05 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.3.0+1" inspector: @@ -354,7 +354,7 @@ packages: description: name: inspector sha256: "40ba0ac1c819c85139bfec9d1e283804581a8985c91f19d00e93212cf29226b1" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.0" intl: @@ -362,7 +362,7 @@ packages: description: name: intl sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.19.0" io: @@ -370,7 +370,7 @@ packages: description: name: io sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.0.5" js: @@ -378,7 +378,7 @@ packages: description: name: js sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.7.1" json_annotation: @@ -386,7 +386,7 @@ packages: description: name: json_annotation sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.9.0" leak_tracker: @@ -394,7 +394,7 @@ packages: description: name: leak_tracker sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "10.0.5" leak_tracker_flutter_testing: @@ -402,7 +402,7 @@ packages: description: name: leak_tracker_flutter_testing sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.0.5" leak_tracker_testing: @@ -410,7 +410,7 @@ packages: description: name: leak_tracker_testing sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.0.1" lints: @@ -418,7 +418,7 @@ packages: description: name: lints sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.0.0" logging: @@ -426,7 +426,7 @@ packages: description: name: logging sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.3.0" macros: @@ -434,7 +434,7 @@ packages: description: name: macros sha256: "0acaed5d6b7eab89f63350bccd82119e6c602df0f391260d0e32b5e23db79536" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.1.2-main.4" matcher: @@ -442,7 +442,7 @@ packages: description: name: matcher sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.12.16+1" material_color_utilities: @@ -450,7 +450,7 @@ packages: description: name: material_color_utilities sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.11.1" math_expressions: @@ -458,7 +458,7 @@ packages: description: name: math_expressions sha256: e32d803d758ace61cc6c4bdfed1226ff60a6a23646b35685670d28b5616139f8 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.6.0" meta: @@ -466,7 +466,7 @@ packages: description: name: meta sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.15.0" mime: @@ -474,7 +474,7 @@ packages: description: name: mime sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.0.0" mocktail: @@ -482,7 +482,7 @@ packages: description: name: mocktail sha256: "890df3f9688106f25755f26b1c60589a92b3ab91a22b8b224947ad041bf172d8" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.0.4" nested: @@ -490,7 +490,7 @@ packages: description: name: nested sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.0.0" package_config: @@ -498,7 +498,7 @@ packages: description: name: package_config sha256: "92d4488434b520a62570293fbd33bb556c7d49230791c1b4bbd973baf6d2dc67" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.1" path: @@ -506,7 +506,7 @@ packages: description: name: path sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.9.0" path_parsing: @@ -514,7 +514,7 @@ packages: description: name: path_parsing sha256: "883402936929eac138ee0a45da5b0f2c80f89913e6dc3bf77eb65b84b409c6ca" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.1.0" petitparser: @@ -522,7 +522,7 @@ packages: description: name: petitparser sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "6.0.2" pool: @@ -530,7 +530,7 @@ packages: description: name: pool sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.5.1" pub_semver: @@ -538,7 +538,7 @@ packages: description: name: pub_semver sha256: "7b3cfbf654f3edd0c6298ecd5be782ce997ddf0e00531b9464b55245185bbbbd" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.5" pubspec_parse: @@ -546,7 +546,7 @@ packages: description: name: pubspec_parse sha256: "81876843eb50dc2e1e5b151792c9a985c5ed2536914115ed04e9c8528f6647b0" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.4.0" recase: @@ -554,7 +554,7 @@ packages: description: name: recase sha256: e4eb4ec2dcdee52dcf99cb4ceabaffc631d7424ee55e56f280bc039737f89213 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.1.0" resizable_widget: @@ -562,7 +562,7 @@ packages: description: name: resizable_widget sha256: db2919754b93f386b9b3fb15e9f48f6c9d6d41f00a24397629133c99df86606a - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.0.5" scroll_pos: @@ -570,7 +570,7 @@ packages: description: name: scroll_pos sha256: cebf602b2dd939de6832bb902ffefb574608d1b84f420b82b381a4007d3c1e1b - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.5.0" shelf: @@ -578,7 +578,7 @@ packages: description: name: shelf sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.4.1" shelf_web_socket: @@ -586,7 +586,7 @@ packages: description: name: shelf_web_socket sha256: cc36c297b52866d203dbf9332263c94becc2fe0ceaa9681d07b6ef9807023b67 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.0.1" sky_engine: @@ -599,7 +599,7 @@ packages: description: name: source_gen sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.5.0" source_span: @@ -607,7 +607,7 @@ packages: description: name: source_span sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.10.0" stack_trace: @@ -615,7 +615,7 @@ packages: description: name: stack_trace sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.11.1" stream_channel: @@ -623,7 +623,7 @@ packages: description: name: stream_channel sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.2" stream_transform: @@ -631,7 +631,7 @@ packages: description: name: stream_transform sha256: ad47125e588cfd37a9a7f86c7d6356dde8dfe89d071d293f80ca9e9273a33871 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.1" string_scanner: @@ -639,7 +639,7 @@ packages: description: name: string_scanner sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.2.0" term_glyph: @@ -647,7 +647,7 @@ packages: description: name: term_glyph sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.2.1" test_api: @@ -655,7 +655,7 @@ packages: description: name: test_api sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.7.2" time: @@ -663,7 +663,7 @@ packages: description: name: time sha256: "370572cf5d1e58adcb3e354c47515da3f7469dac3a95b447117e728e7be6f461" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.5" timing: @@ -671,7 +671,7 @@ packages: description: name: timing sha256: "62ee18aca144e4a9f29d212f5a4c6a053be252b895ab14b5821996cff4ed90fe" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.0.2" typed_data: @@ -679,7 +679,7 @@ packages: description: name: typed_data sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.4.0" vector_graphics_codec: @@ -687,7 +687,7 @@ packages: description: name: vector_graphics_codec sha256: "99fd9fbd34d9f9a32efd7b6a6aae14125d8237b10403b422a6a6dfeac2806146" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.1.13" vector_graphics_compiler: @@ -695,7 +695,7 @@ packages: description: name: vector_graphics_compiler sha256: "1b4b9e706a10294258727674a340ae0d6e64a7231980f9f9a3d12e4b42407aad" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.1.16" vector_math: @@ -703,7 +703,7 @@ packages: description: name: vector_math sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.4" vm_service: @@ -711,7 +711,7 @@ packages: description: name: vm_service sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "14.2.5" watcher: @@ -719,7 +719,7 @@ packages: description: name: watcher sha256: "69da27e49efa56a15f8afe8f4438c4ec02eff0a117df1b22ea4aad194fe1c104" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.1.1" web: @@ -727,7 +727,7 @@ packages: description: name: web sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.1.0" web_socket: @@ -735,7 +735,7 @@ packages: description: name: web_socket sha256: "3c12d96c0c9a4eec095246debcea7b86c0324f22df69893d538fcc6f1b8cce83" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.1.6" web_socket_channel: @@ -743,7 +743,7 @@ packages: description: name: web_socket_channel sha256: "9f187088ed104edd8662ca07af4b124465893caf063ba29758f97af57e61da8f" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.0.1" widgetbook: @@ -751,7 +751,7 @@ packages: description: name: widgetbook sha256: "8738bfa29cc314b68ac5068cb0d086a0ddf8db4e167d0e4d0f539e1ad1042949" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.10.2" widgetbook_annotation: @@ -759,7 +759,7 @@ packages: description: name: widgetbook_annotation sha256: "08570e3568275c4c283cdf78409c125f86c96c9b4f94f0a390d6a163349e9934" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.2.0" widgetbook_generator: @@ -767,7 +767,7 @@ packages: description: name: widgetbook_generator sha256: d664ba02805c37ef4bf2a061493a6ec254b40f0d14c5546311566226d71845a2 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.9.1" xml: @@ -775,7 +775,7 @@ packages: description: name: xml sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "6.5.0" yaml: @@ -783,7 +783,7 @@ packages: description: name: yaml sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.1.3" sdks: From af49c74e27ff00999c098fb5f4f6f21e8492a845 Mon Sep 17 00:00:00 2001 From: PouriaMoradi021 Date: Thu, 16 Jan 2025 14:23:55 +0330 Subject: [PATCH 2/6] update: fixing `FilledButton` in `buttonStyle` & `ButtonContent` - add/create `RequestStateEnum` for handling different state of components - add/create `AdaptiveButtonContentWidget` - update `AdaptivePrimaryButton` - update `adaptivePrimaryButtonUseCase` - update `AppThemeData` & add `lightAccentColors` & `darkAccentColors` - update `main` file & add a knobs for selecting & changing accent colors - update `main.directories.dart` - code style --- lib/main.dart | 72 ++++++------------- lib/main.directories.g.dart | 2 +- lib/src/core/enum/request_state_enum.dart | 6 ++ lib/src/core/theme/app_theme_data.dart | 30 +++++++- .../adaptive_primary_button.dart | 49 +++++++------ .../adaptive_primary_button_usecase.dart | 18 +++-- .../adaptive_button_content_widget.dart | 39 ++++++++++ 7 files changed, 133 insertions(+), 83 deletions(-) create mode 100644 lib/src/core/enum/request_state_enum.dart create mode 100644 lib/src/features/widgets/buttons/core/common/widgets/adaptive_button_content_widget.dart diff --git a/lib/main.dart b/lib/main.dart index d1ecdfc..012ce51 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -14,48 +14,6 @@ void main() { runApp(const WidgetBookApp()); } -/// ## [WidgetBookApp] Class Documentation -/// -/// The `WidgetBookApp` class is the main entry point for -/// the Widgetbook application. -/// It defines the Widgetbook configuration, including the devices, -/// themes, and addons used for visualizing and testing widgets. -/// -/// ### Usage: -/// -/// The `WidgetBookApp` sets up a Widgetbook environment with -/// predefined themes, devices, and alignment options. -/// It enables developers to test their widgets in different -/// contexts and layouts. -/// -/// ### Addons: -/// -/// - **[DeviceFrameAddon]**: -/// - Includes a list of devices for testing widgets. -/// - **Devices**: -/// - `Devices.ios.iPhone13`: Simulates an iPhone 13 device. -/// - `Devices.windows.laptop`: Simulates a standard laptop. -/// - `Devices.windows.wideMonitor`: Simulates a widescreen monitor. -/// -/// - **[AlignmentAddon]**: -/// - Allows testing widget alignment within the parent container. -/// -/// - **[ThemeAddon]**: -/// - Provides two themes for testing: -/// - **Light Theme**: Uses `AppThemeData.lightTheme()` for a -/// bright interface. -/// - **Dark Theme**: Uses `AppThemeData.darkTheme()` for a -/// darker interface. -/// - Includes a custom theme builder that wraps widgets with -/// `AppTheme` and `AppScaffold`. -/// -/// ### Properties: -/// -/// - **[directories]**: -/// - Dynamically generated list of widget directories. -/// - Facilitates organizing and testing widgets within Widgetbook. -/// - @widgetbook.App() class WidgetBookApp extends StatelessWidget { const WidgetBookApp({super.key}); @@ -89,28 +47,42 @@ class WidgetBookApp extends StatelessWidget { themes: [ WidgetbookTheme( name: 'Light', - data: AppThemeData.lightTheme(), + data: AppThemeData.lightTheme(AppThemeData.lightAccentColors[0]), ), WidgetbookTheme( name: 'Dark', - data: AppThemeData.darkTheme(), - ) + data: AppThemeData.darkTheme(AppThemeData.darkAccentColors[0]), + ), ], themeBuilder: (context, data, child) { + final isLightTheme = data.brightness == Brightness.light; + + final selectedAccentColor = context.knobs.list( + label: 'Accent Color', + description: 'Select an accent color for the theme.', + options: isLightTheme + ? AppThemeData.lightAccentColors + : AppThemeData.darkAccentColors, + initialOption: isLightTheme + ? AppThemeData.lightAccentColors[0] + : AppThemeData.darkAccentColors[0], + ); + + final themeWithAccent = isLightTheme + ? AppThemeData.lightTheme(selectedAccentColor) + : AppThemeData.darkTheme(selectedAccentColor); + return FluentApp( debugShowCheckedModeBanner: false, - theme: data, - themeMode: ThemeMode.light, + theme: themeWithAccent, home: AppTheme( - themeData: data, + themeData: themeWithAccent, child: AppScaffold(child: child), ), ); }, ), ], - // The [directories] variable does not exist yet, - // it will be generated in the next step directories: directories, ); } diff --git a/lib/main.directories.g.dart b/lib/main.directories.g.dart index 6054c62..94962a4 100644 --- a/lib/main.directories.g.dart +++ b/lib/main.directories.g.dart @@ -36,7 +36,7 @@ final directories = <_i1.WidgetbookNode>[ name: 'AdaptivePrimaryButton', useCase: _i1.WidgetbookUseCase( name: 'Fluent Button with Knobs', - builder: _i2.fluentButtonUseCase, + builder: _i2.adaptivePrimaryButtonUseCase, ), ) ], diff --git a/lib/src/core/enum/request_state_enum.dart b/lib/src/core/enum/request_state_enum.dart new file mode 100644 index 0000000..a9dae03 --- /dev/null +++ b/lib/src/core/enum/request_state_enum.dart @@ -0,0 +1,6 @@ +enum RequestStateEnum { + initial, + loading, + loaded, + error, +} diff --git a/lib/src/core/theme/app_theme_data.dart b/lib/src/core/theme/app_theme_data.dart index f121372..572571f 100644 --- a/lib/src/core/theme/app_theme_data.dart +++ b/lib/src/core/theme/app_theme_data.dart @@ -55,16 +55,42 @@ class AppThemeData { OnSurfacePallet.dark, ]; - static FluentThemeData lightTheme() => FluentThemeData( + static const List lightAccentColors = [ + Color(0xFF0A4D7E), + Color(0xFFD4540A), + Color(0xFFA7101A), + Color(0xFF7F0080), + Color(0xFF5C3E83), + Color(0xFF008D7A), + Color(0xFF0C5C0C), + Color(0xFF0F0E32), + ]; + + static const List darkAccentColors = [ + Color(0xFF0F6CBD), + Color(0xFFF7630C), + Color(0xFFE81123), + Color(0xFFB4009E), + Color(0xFF744DA9), + Color(0xFF00B294), + Color(0xFF107C10), + Color(0xFF131440), + ]; + + static FluentThemeData lightTheme(Color selectedAccentColor) => + FluentThemeData( brightness: Brightness.light, typography: typography, extensions: lightExtensions, + accentColor: selectedAccentColor.toAccentColor(), ); - static FluentThemeData darkTheme() => FluentThemeData( + static FluentThemeData darkTheme(Color selectedAccentColor) => + FluentThemeData( brightness: Brightness.dark, typography: typography, extensions: darkExtensions, + accentColor: selectedAccentColor.toAccentColor(), ); static Typography typography = const Typography.raw( diff --git a/lib/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button.dart b/lib/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button.dart index 88e923e..7e172de 100644 --- a/lib/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button.dart +++ b/lib/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button.dart @@ -1,47 +1,46 @@ import 'package:fluent_ui/fluent_ui.dart'; +import 'package:pactus_gui_widgetbook/app_styles.dart'; +import 'package:pactus_gui_widgetbook/src/core/enum/request_state_enum.dart'; +import 'package:pactus_gui_widgetbook/src/features/widgets/buttons/core/common/widgets/adaptive_button_content_widget.dart'; class AdaptivePrimaryButton extends StatelessWidget { - const AdaptivePrimaryButton( - {super.key, required this.text, this.onPressed, required this.disabled}); - final String text; + const AdaptivePrimaryButton({ + super.key, + required this.title, + this.onPressed, + required this.requestState, + }); + + final String title; final VoidCallback? onPressed; - final bool disabled; + final RequestStateEnum requestState; + @override Widget build(BuildContext context) { + final theme = FluentTheme.of(context); + return FilledButton( - onPressed: disabled ? null : onPressed, + onPressed: (requestState == RequestStateEnum.loading) ? null : onPressed, style: ButtonStyle( backgroundColor: WidgetStateProperty.resolveWith((states) { if (states.contains(WidgetState.disabled)) { - return Colors.grey[100]; + return AppTheme.of(context).extension()!.surface1!; } else if (states.contains(WidgetState.pressed)) { - return Colors.blue.darker; + return theme.accentColor.darker; } else if (states.contains(WidgetState.hovered)) { - return Colors.blue.dark; - } - return Colors.blue; - }), - foregroundColor: WidgetStateProperty.resolveWith((states) { - if (states.contains(WidgetState.disabled)) { - return Colors.grey[120]; + return theme.accentColor.darker; } - return Colors.white; + return theme.accentColor; }), shape: WidgetStateProperty.resolveWith((states) { return RoundedRectangleBorder( - side: BorderSide( - color: states.contains(WidgetState.disabled) - ? Colors.grey[130] - : Colors.blue.darker, - width: 2, - ), - borderRadius: BorderRadius.circular(8), + borderRadius: BorderRadius.circular(4), ); }), ), - child: Text( - text, - style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600), + child: AdaptiveButtonContentWidget( + title: title, + requestState: requestState, ), ); } diff --git a/lib/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button_usecase.dart b/lib/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button_usecase.dart index f708a4a..7995dc4 100644 --- a/lib/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button_usecase.dart +++ b/lib/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button_usecase.dart @@ -1,10 +1,17 @@ import 'package:fluent_ui/fluent_ui.dart'; +import 'package:pactus_gui_widgetbook/src/core/enum/request_state_enum.dart'; import 'package:pactus_gui_widgetbook/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button.dart'; import 'package:widgetbook/widgetbook.dart'; import 'package:widgetbook_annotation/widgetbook_annotation.dart'; @UseCase(name: 'Fluent Button with Knobs', type: AdaptivePrimaryButton) -Widget fluentButtonUseCase(BuildContext context) { +Widget adaptivePrimaryButtonUseCase(BuildContext context) { + final requestState = context.knobs.list( + label: 'Request State', + options: RequestStateEnum.values, + initialOption: RequestStateEnum.loaded, + ); + final text = context.knobs.string( label: 'Button Text', initialValue: 'Click Me', @@ -17,14 +24,15 @@ Widget fluentButtonUseCase(BuildContext context) { description: 'Enable or disable the button.', ); - return Center( + return SizedBox( + width: 200, child: AdaptivePrimaryButton( - text: text, - disabled: isDisabled, + title: text, + requestState: requestState, onPressed: isDisabled ? null : () { - debugPrint('Button Pressed'); + debugPrint('Adaptive Primary Button Pressed'); }, ), ); diff --git a/lib/src/features/widgets/buttons/core/common/widgets/adaptive_button_content_widget.dart b/lib/src/features/widgets/buttons/core/common/widgets/adaptive_button_content_widget.dart new file mode 100644 index 0000000..b6733aa --- /dev/null +++ b/lib/src/features/widgets/buttons/core/common/widgets/adaptive_button_content_widget.dart @@ -0,0 +1,39 @@ +import 'package:fluent_ui/fluent_ui.dart'; +import 'package:pactus_gui_widgetbook/app_styles.dart'; +import 'package:pactus_gui_widgetbook/src/core/enum/request_state_enum.dart'; + +class AdaptiveButtonContentWidget extends StatelessWidget { + const AdaptiveButtonContentWidget({ + super.key, + required this.title, + required this.requestState, + }); + + final String title; + final RequestStateEnum requestState; + + @override + Widget build(BuildContext context) { + switch (requestState) { + /// TODO (by Pouria): add loading & error state after defining by UI team + case RequestStateEnum.loading: + return const SizedBox(); + case RequestStateEnum.initial: + case RequestStateEnum.loaded: + return SizedBox( + height: 32, + child: Center( + child: Text( + title, + style: InterTextStyles.body.copyWith( + color: + AppTheme.of(context).extension()!.surface3!, + ), + ), + ), + ); + case RequestStateEnum.error: + return const SizedBox(); + } + } +} From f6f819f8a663f29e0a4946fcab96838cd52f6e29 Mon Sep 17 00:00:00 2001 From: PouriaMoradi021 Date: Thu, 16 Jan 2025 14:58:52 +0330 Subject: [PATCH 3/6] feat: add/create `AdaptiveSecondaryButton` components - add/create `AdaptiveSecondaryButton` widget - add/create `adaptiveSecondaryButtonUseCase` - add/create `AppColors` --- lib/main.directories.g.dart | 30 ++++++-- lib/src/core/pallets/colors/app_colors.dart | 6 ++ .../adaptive_primary_button_usecase.dart | 3 +- .../adaptive_secondary_button.dart | 77 +++++++++++++++++++ .../adaptive_secondary_button_usecase.dart | 40 ++++++++++ 5 files changed, 147 insertions(+), 9 deletions(-) create mode 100644 lib/src/core/pallets/colors/app_colors.dart create mode 100644 lib/src/features/widgets/buttons/adaptive_secondary_button/adaptive_secondary_button.dart create mode 100644 lib/src/features/widgets/buttons/adaptive_secondary_button/adaptive_secondary_button_usecase.dart diff --git a/lib/main.directories.g.dart b/lib/main.directories.g.dart index 94962a4..df2eabf 100644 --- a/lib/main.directories.g.dart +++ b/lib/main.directories.g.dart @@ -11,12 +11,14 @@ // ignore_for_file: no_leading_underscores_for_library_prefixes import 'package:pactus_gui_widgetbook/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button_usecase.dart' as _i2; -import 'package:pactus_gui_widgetbook/src/features/widgets/counter/counter_usecase.dart' +import 'package:pactus_gui_widgetbook/src/features/widgets/buttons/adaptive_secondary_button/adaptive_secondary_button_usecase.dart' as _i3; -import 'package:pactus_gui_widgetbook/src/features/widgets/custom_button/custom_button_usecase.dart' +import 'package:pactus_gui_widgetbook/src/features/widgets/counter/counter_usecase.dart' as _i4; -import 'package:pactus_gui_widgetbook/src/features/widgets/custom_text/custom_text_usecase.dart' +import 'package:pactus_gui_widgetbook/src/features/widgets/custom_button/custom_button_usecase.dart' as _i5; +import 'package:pactus_gui_widgetbook/src/features/widgets/custom_text/custom_text_usecase.dart' + as _i6; import 'package:widgetbook/widgetbook.dart' as _i1; final directories = <_i1.WidgetbookNode>[ @@ -35,12 +37,24 @@ final directories = <_i1.WidgetbookNode>[ _i1.WidgetbookLeafComponent( name: 'AdaptivePrimaryButton', useCase: _i1.WidgetbookUseCase( - name: 'Fluent Button with Knobs', + name: 'Adaptive Primary Button with Knobs', builder: _i2.adaptivePrimaryButtonUseCase, ), ) ], - ) + ), + _i1.WidgetbookFolder( + name: 'adaptive_secondary_button', + children: [ + _i1.WidgetbookLeafComponent( + name: 'AdaptiveSecondaryButton', + useCase: _i1.WidgetbookUseCase( + name: 'Adaptive Secondary Button with Knobs', + builder: _i3.adaptiveSecondaryButtonUseCase, + ), + ) + ], + ), ], ), _i1.WidgetbookFolder( @@ -50,7 +64,7 @@ final directories = <_i1.WidgetbookNode>[ name: 'CounterWidget', useCase: _i1.WidgetbookUseCase( name: 'Counter with Knobs', - builder: _i3.counterWidgetUseCase, + builder: _i4.counterWidgetUseCase, ), ) ], @@ -62,7 +76,7 @@ final directories = <_i1.WidgetbookNode>[ name: 'CustomButtonWidget', useCase: _i1.WidgetbookUseCase( name: 'Custom Button with Knobs', - builder: _i4.customButtonWidgetUseCase, + builder: _i5.customButtonWidgetUseCase, ), ) ], @@ -74,7 +88,7 @@ final directories = <_i1.WidgetbookNode>[ name: 'CustomTextWidget', useCase: _i1.WidgetbookUseCase( name: 'Select the text to display from the dropdown', - builder: _i5.customTextWidgetUseCase, + builder: _i6.customTextWidgetUseCase, ), ) ], diff --git a/lib/src/core/pallets/colors/app_colors.dart b/lib/src/core/pallets/colors/app_colors.dart new file mode 100644 index 0000000..b213edc --- /dev/null +++ b/lib/src/core/pallets/colors/app_colors.dart @@ -0,0 +1,6 @@ +import 'package:fluent_ui/fluent_ui.dart'; + +class AppColors { + AppColors._(); + static const borderColor = Color(0xFFC7C7C7); +} diff --git a/lib/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button_usecase.dart b/lib/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button_usecase.dart index 7995dc4..493b788 100644 --- a/lib/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button_usecase.dart +++ b/lib/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button_usecase.dart @@ -4,7 +4,8 @@ import 'package:pactus_gui_widgetbook/src/features/widgets/buttons/adaptive_prim import 'package:widgetbook/widgetbook.dart'; import 'package:widgetbook_annotation/widgetbook_annotation.dart'; -@UseCase(name: 'Fluent Button with Knobs', type: AdaptivePrimaryButton) +@UseCase( + name: 'Adaptive Primary Button with Knobs', type: AdaptivePrimaryButton) Widget adaptivePrimaryButtonUseCase(BuildContext context) { final requestState = context.knobs.list( label: 'Request State', diff --git a/lib/src/features/widgets/buttons/adaptive_secondary_button/adaptive_secondary_button.dart b/lib/src/features/widgets/buttons/adaptive_secondary_button/adaptive_secondary_button.dart new file mode 100644 index 0000000..a0c2f6f --- /dev/null +++ b/lib/src/features/widgets/buttons/adaptive_secondary_button/adaptive_secondary_button.dart @@ -0,0 +1,77 @@ +import 'package:fluent_ui/fluent_ui.dart'; +import 'package:pactus_gui_widgetbook/app_styles.dart'; +import 'package:pactus_gui_widgetbook/src/core/enum/request_state_enum.dart'; +import 'package:pactus_gui_widgetbook/src/core/pallets/colors/app_colors.dart'; +import 'package:pactus_gui_widgetbook/src/features/widgets/buttons/core/common/widgets/adaptive_button_content_widget.dart'; + +class AdaptiveSecondaryButton extends StatelessWidget { + const AdaptiveSecondaryButton({ + super.key, + required this.title, + this.onPressed, + required this.requestState, + }); + + final String title; + final VoidCallback? onPressed; + final RequestStateEnum requestState; + + @override + Widget build(BuildContext context) { + return OutlinedButton( + onPressed: (requestState == RequestStateEnum.loading) ? null : onPressed, + style: ButtonStyle( + shape: WidgetStateProperty.resolveWith((states) { + if (states.contains(WidgetState.disabled)) { + return RoundedRectangleBorder( + borderRadius: BorderRadius.circular(4), + side: const BorderSide( + color: AppColors.borderColor, + width: 1, + ), + ); + } + if (states.contains(WidgetState.pressed)) { + return RoundedRectangleBorder( + borderRadius: BorderRadius.circular(4), + side: const BorderSide( + color: AppColors.borderColor, + width: 1, + ), + ); + } + if (states.contains(WidgetState.hovered)) { + return RoundedRectangleBorder( + borderRadius: BorderRadius.circular(4), + side: const BorderSide( + color: AppColors.borderColor, + width: 1, + ), + ); + } + return RoundedRectangleBorder( + borderRadius: BorderRadius.circular(4), + side: const BorderSide( + color: AppColors.borderColor, + width: 1, + ), + ); + }), + foregroundColor: WidgetStateProperty.resolveWith((states) { + if (states.contains(WidgetState.disabled)) { + return AppTheme.of(context).extension()!.surface1!; + } else if (states.contains(WidgetState.pressed)) { + return AppTheme.of(context).extension()!.surface1!; + } else if (states.contains(WidgetState.hovered)) { + return AppTheme.of(context).extension()!.surface1!; + } + return AppTheme.of(context).extension()!.surface1; + }), + ), + child: AdaptiveButtonContentWidget( + title: title, + requestState: requestState, + ), + ); + } +} diff --git a/lib/src/features/widgets/buttons/adaptive_secondary_button/adaptive_secondary_button_usecase.dart b/lib/src/features/widgets/buttons/adaptive_secondary_button/adaptive_secondary_button_usecase.dart new file mode 100644 index 0000000..07ae2db --- /dev/null +++ b/lib/src/features/widgets/buttons/adaptive_secondary_button/adaptive_secondary_button_usecase.dart @@ -0,0 +1,40 @@ +import 'package:fluent_ui/fluent_ui.dart'; +import 'package:pactus_gui_widgetbook/src/core/enum/request_state_enum.dart'; +import 'package:pactus_gui_widgetbook/src/features/widgets/buttons/adaptive_secondary_button/adaptive_secondary_button.dart'; +import 'package:widgetbook/widgetbook.dart'; +import 'package:widgetbook_annotation/widgetbook_annotation.dart'; + +@UseCase( + name: 'Adaptive Secondary Button with Knobs', type: AdaptiveSecondaryButton) +Widget adaptiveSecondaryButtonUseCase(BuildContext context) { + final requestState = context.knobs.list( + label: 'Request State', + options: RequestStateEnum.values, + initialOption: RequestStateEnum.loaded, + ); + + final text = context.knobs.string( + label: 'Button Text', + initialValue: 'Click Me', + description: 'Set the text displayed on the button.', + ); + + final isDisabled = context.knobs.boolean( + label: 'Disabled', + initialValue: false, + description: 'Enable or disable the button.', + ); + + return SizedBox( + width: 200, + child: AdaptiveSecondaryButton( + title: text, + requestState: requestState, + onPressed: isDisabled + ? null + : () { + debugPrint('Adaptive Secondary Button Pressed'); + }, + ), + ); +} From 4f548f4ed280a3f376e0fce954ad7f1f0b8dc00c Mon Sep 17 00:00:00 2001 From: PouriaMoradi021 Date: Thu, 16 Jan 2025 20:03:17 +0330 Subject: [PATCH 4/6] test: add test for button components - add some tests for different states of `AdaptivePrimaryButton` - add some tests for different states of `AdaptiveSecondaryButton` --- .../adaptive_primary_button_test.dart | 113 ++++++++++++++++++ .../adaptive_secondary_button_test.dart | 112 +++++++++++++++++ 2 files changed, 225 insertions(+) create mode 100644 test/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button_test.dart create mode 100644 test/features/widgets/buttons/adaptive_secondary_button/adaptive_secondary_button_test.dart diff --git a/test/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button_test.dart b/test/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button_test.dart new file mode 100644 index 0000000..a63255b --- /dev/null +++ b/test/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button_test.dart @@ -0,0 +1,113 @@ +import 'package:fluent_ui/fluent_ui.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:pactus_gui_widgetbook/app_styles.dart'; +import 'package:pactus_gui_widgetbook/src/core/enum/request_state_enum.dart'; +import 'package:pactus_gui_widgetbook/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button.dart'; + +void main() { + group('AdaptivePrimaryButton', () { + late bool wasPressed; + + setUp(() { + wasPressed = false; + }); + + Widget createTestableWidget({ + required String title, + required RequestStateEnum requestState, + required VoidCallback? onPressed, + required FluentThemeData themeWithAccent, + }) { + return FluentApp( + debugShowCheckedModeBanner: false, + theme: themeWithAccent, + home: AppTheme( + themeData: themeWithAccent, + child: ScaffoldPage( + content: Center( + child: AdaptivePrimaryButton( + title: title, + requestState: requestState, + onPressed: onPressed, + ), + ), + ), + ), + ); + } + + testWidgets('renders correctly and is clickable when loaded', (WidgetTester tester) async { + const testTitle = 'Test Button'; + final themeWithAccent = AppThemeData.lightTheme(const Color(0xFF0A4D7E)); + + await tester.pumpWidget(createTestableWidget( + title: testTitle, + requestState: RequestStateEnum.loaded, + onPressed: () { + wasPressed = true; + }, + themeWithAccent: themeWithAccent, + )); + + expect(find.text(testTitle), findsOneWidget); + + final button = find.byType(FilledButton); + expect(tester.widget(button).onPressed, isNotNull); + + await tester.tap(button); + await tester.pumpAndSettle(); + + expect(wasPressed, isTrue); + }); + + testWidgets('renders correctly and is disabled when loading', (WidgetTester tester) async { + const testTitle = 'Loading Button'; + final themeWithAccent = AppThemeData.lightTheme(const Color(0xFF0A4D7E)); + + await tester.pumpWidget(createTestableWidget( + title: testTitle, + requestState: RequestStateEnum.loading, + onPressed: () { + wasPressed = true; + }, + themeWithAccent: themeWithAccent, + )); + + expect(find.text(testTitle), findsNothing); + + expect(find.byType(SizedBox), findsWidgets); + + final button = find.byType(FilledButton); + expect(tester.widget(button).onPressed, isNull); + + await tester.tap(button); + await tester.pumpAndSettle(); + expect(wasPressed, isFalse); + }); + + + testWidgets('renders correctly with dark theme', (WidgetTester tester) async { + const testTitle = 'Dark Theme Button'; + final themeWithAccent = AppThemeData.darkTheme(const Color(0xFF0F6CBD)); + + await tester.pumpWidget(createTestableWidget( + title: testTitle, + requestState: RequestStateEnum.loaded, + onPressed: () { + wasPressed = true; + }, + themeWithAccent: themeWithAccent, + )); + + expect(find.text(testTitle), findsOneWidget); + + final button = find.byType(FilledButton); + expect(tester.widget(button).onPressed, isNotNull); + + await tester.tap(button); + await tester.pumpAndSettle(); + + expect(wasPressed, isTrue); + }); + }); +} diff --git a/test/features/widgets/buttons/adaptive_secondary_button/adaptive_secondary_button_test.dart b/test/features/widgets/buttons/adaptive_secondary_button/adaptive_secondary_button_test.dart new file mode 100644 index 0000000..cb51844 --- /dev/null +++ b/test/features/widgets/buttons/adaptive_secondary_button/adaptive_secondary_button_test.dart @@ -0,0 +1,112 @@ +import 'package:fluent_ui/fluent_ui.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:pactus_gui_widgetbook/app_styles.dart'; +import 'package:pactus_gui_widgetbook/src/core/enum/request_state_enum.dart'; +import 'package:pactus_gui_widgetbook/src/features/widgets/buttons/adaptive_secondary_button/adaptive_secondary_button.dart'; + +void main() { + group('AdaptiveSecondaryButton', () { + late bool wasPressed; + + setUp(() { + wasPressed = false; + }); + + Widget createTestableWidget({ + required String title, + required RequestStateEnum requestState, + required VoidCallback? onPressed, + required FluentThemeData themeWithAccent, + }) { + return FluentApp( + debugShowCheckedModeBanner: false, + theme: themeWithAccent, + home: AppTheme( + themeData: themeWithAccent, + child: ScaffoldPage( + content: Center( + child: AdaptiveSecondaryButton( + title: title, + requestState: requestState, + onPressed: onPressed, + ), + ), + ), + ), + ); + } + + testWidgets('renders correctly and is clickable when loaded', (WidgetTester tester) async { + const testTitle = 'Test Button'; + final themeWithAccent = AppThemeData.lightTheme(const Color(0xFF0A4D7E)); + + await tester.pumpWidget(createTestableWidget( + title: testTitle, + requestState: RequestStateEnum.loaded, + onPressed: () { + wasPressed = true; + }, + themeWithAccent: themeWithAccent, + )); + + expect(find.text(testTitle), findsOneWidget); + + final button = find.byType(OutlinedButton); + expect(tester.widget(button).onPressed, isNotNull); + + await tester.tap(button); + await tester.pumpAndSettle(); + + expect(wasPressed, isTrue); + }); + + testWidgets('renders correctly and is disabled when loading', (WidgetTester tester) async { + const testTitle = 'Loading Button'; + final themeWithAccent = AppThemeData.lightTheme(const Color(0xFF0A4D7E)); + + await tester.pumpWidget(createTestableWidget( + title: testTitle, + requestState: RequestStateEnum.loading, + onPressed: () { + wasPressed = true; + }, + themeWithAccent: themeWithAccent, + )); + + expect(find.text(testTitle), findsNothing); + + expect(find.byType(SizedBox), findsWidgets); + + final button = find.byType(OutlinedButton); + expect(tester.widget(button).onPressed, isNull); + + await tester.tap(button); + await tester.pumpAndSettle(); + expect(wasPressed, isFalse); + }); + + testWidgets('renders correctly with dark theme', (WidgetTester tester) async { + const testTitle = 'Dark Theme Button'; + final themeWithAccent = AppThemeData.darkTheme(const Color(0xFF0F6CBD)); + + await tester.pumpWidget(createTestableWidget( + title: testTitle, + requestState: RequestStateEnum.loaded, + onPressed: () { + wasPressed = true; + }, + themeWithAccent: themeWithAccent, + )); + + expect(find.text(testTitle), findsOneWidget); + + final button = find.byType(OutlinedButton); + expect(tester.widget(button).onPressed, isNotNull); + + await tester.tap(button); + await tester.pumpAndSettle(); + + expect(wasPressed, isTrue); + }); + }); +} From 05368fa55e3da409c0f94b11d551fafa76f3c321 Mon Sep 17 00:00:00 2001 From: PouriaMoradi021 Date: Fri, 17 Jan 2025 15:04:20 +0330 Subject: [PATCH 5/6] docs: add documents according to mark down standards --- lib/src/core/enum/request_state_enum.dart | 23 +++++++++ lib/src/core/theme/app_theme_data.dart | 48 +++++++++---------- .../adaptive_primary_button.dart | 26 ++++++++++ .../adaptive_primary_button_usecase.dart | 32 +++++++++++++ .../adaptive_secondary_button.dart | 24 ++++++++++ .../adaptive_secondary_button_usecase.dart | 31 ++++++++++++ .../adaptive_button_content_widget.dart | 24 ++++++++++ 7 files changed, 182 insertions(+), 26 deletions(-) diff --git a/lib/src/core/enum/request_state_enum.dart b/lib/src/core/enum/request_state_enum.dart index a9dae03..3254f5d 100644 --- a/lib/src/core/enum/request_state_enum.dart +++ b/lib/src/core/enum/request_state_enum.dart @@ -1,3 +1,26 @@ +/// ## [RequestStateEnum] Enum Documentation +/// +/// The `RequestStateEnum` represents the various states a request can be in +/// during its lifecycle. +/// +/// ### States: +/// +/// - **[initial]**: +/// - Indicates the initial state of the request before any operation +/// has started. +/// +/// - **[loading]**: +/// - Represents the state where the request is in progress and loading. +/// +/// - **[loaded]**: +/// - Indicates that the request has been completed successfully, +/// and the data is available. +/// +/// - **[error]**: +/// - Represents a state where the request has failed due to an error. +/// +library; + enum RequestStateEnum { initial, loading, diff --git a/lib/src/core/theme/app_theme_data.dart b/lib/src/core/theme/app_theme_data.dart index 572571f..32c7ccc 100644 --- a/lib/src/core/theme/app_theme_data.dart +++ b/lib/src/core/theme/app_theme_data.dart @@ -2,47 +2,43 @@ import 'package:fluent_ui/fluent_ui.dart'; import 'package:pactus_gui_widgetbook/src/core/pallets/on_surface_pallet.dart'; import 'package:pactus_gui_widgetbook/src/core/pallets/surface_pallet.dart'; import 'package:pactus_gui_widgetbook/src/core/text_styles/inter_text_styles.dart'; - /// ## [AppThemeData] Class Documentation /// -/// The `AppThemeData` class provides a centralized definition of -/// the application's themes and typography. -/// It is designed to support both light and dark modes and uses -/// `FluentThemeData` for configuration. +/// The `AppThemeData` class defines the theme settings for the application, +/// including light and dark themes, color palettes, and typography. /// /// ### Usage: /// -/// This class offers methods and properties to retrieve predefined -/// themes and typography for the application. -/// It also supports custom theme extensions through the use of -/// `ThemeExtension`. +/// This class provides methods to create `FluentThemeData` instances +/// for light and dark themes, which can be customized with a +/// selected accent color. It integrates Fluent UI theming capabilities +/// with application-specific extensions and styles. /// /// ### Properties: /// /// - **[lightExtensions]**: -/// - A collection of `ThemeExtension` objects for the light theme. -/// - Includes `SurfacePallet.light` and `OnSurfacePallet.light`. +/// - A collection of `ThemeExtension` objects used for the light theme. +/// - Includes surface and on-surface palettes +/// (`SurfacePallet.light` and `OnSurfacePallet.light`). /// /// - **[darkExtensions]**: -/// - A collection of `ThemeExtension` objects for the dark theme. -/// - Includes `SurfacePallet.dark` and `OnSurfacePallet.dark`. -/// -/// - **[typography]**: -/// - An instance of `Typography` defining text styles for various use cases. -/// - Includes properties like `subtitle`, `title`, `bodyStrong`, -/// `caption`, `body`, and more. -/// - Uses `InterTextStyles` for text style definitions. +/// - A collection of `ThemeExtension` objects used for the dark theme. +/// - Includes surface and on-surface palettes +/// (`SurfacePallet.dark` and `OnSurfacePallet.dark`). /// -/// ### Methods: +/// - **[lightAccentColors]**: +/// - A predefined list of accent colors for the light theme. +/// - Includes colors like `Color(0xFF0A4D7E)` and `Color(0xFFD4540A)`. /// -/// - **[lightTheme()]**: -/// - Returns a `FluentThemeData` instance configured for light mode. -/// - Includes light extensions and typography. +/// - **[darkAccentColors]**: +/// - A predefined list of accent colors for the dark theme. +/// - Includes colors like `Color(0xFF0F6CBD)` and `Color(0xFFF7630C)`. /// -/// - **[darkTheme()]**: -/// - Returns a `FluentThemeData` instance configured for dark mode. -/// - Includes dark extensions and typography. +/// - **[typography]**: +/// - A `Typography` object defining text styles used across the app. +/// - Includes styles for subtitles, titles, captions, and body text. /// + class AppThemeData { AppThemeData._(); static const Iterable> lightExtensions = [ diff --git a/lib/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button.dart b/lib/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button.dart index 7e172de..393821b 100644 --- a/lib/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button.dart +++ b/lib/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button.dart @@ -2,6 +2,32 @@ import 'package:fluent_ui/fluent_ui.dart'; import 'package:pactus_gui_widgetbook/app_styles.dart'; import 'package:pactus_gui_widgetbook/src/core/enum/request_state_enum.dart'; import 'package:pactus_gui_widgetbook/src/features/widgets/buttons/core/common/widgets/adaptive_button_content_widget.dart'; +/// ## [AdaptivePrimaryButton] Class Documentation +/// +/// The AdaptivePrimaryButton class is a reusable widget for creating +/// a primary button with adaptive states and styles. +/// It integrates seamlessly with Fluent UI themes and supports different +/// request states for dynamic behavior. +/// +/// ### Usage: +/// +/// This button adapts its style and functionality based on +/// its request state (e.g., loading, disabled). It uses +/// Fluent UI's `FilledButton` and allows custom actions via +/// the `onPressed` callback. +/// +/// ### Properties: +/// +/// - **[title]** (String): +/// - The text label displayed on the button. +/// +/// - **[onPressed]** (VoidCallback?): +/// - The callback function triggered when the button is pressed. +/// - Disabled if the request state is `RequestStateEnum.loading`. +/// +/// - **[requestState]** (RequestStateEnum): +/// - Represents the current state of the button (e.g., loading, idle). +/// class AdaptivePrimaryButton extends StatelessWidget { const AdaptivePrimaryButton({ diff --git a/lib/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button_usecase.dart b/lib/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button_usecase.dart index 493b788..0d604e0 100644 --- a/lib/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button_usecase.dart +++ b/lib/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button_usecase.dart @@ -3,6 +3,38 @@ import 'package:pactus_gui_widgetbook/src/core/enum/request_state_enum.dart'; import 'package:pactus_gui_widgetbook/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button.dart'; import 'package:widgetbook/widgetbook.dart'; import 'package:widgetbook_annotation/widgetbook_annotation.dart'; +/// ## [adaptivePrimaryButtonUseCase] Function Documentation +/// +/// The `adaptivePrimaryButtonUseCase` function is a Widgetbook +/// use case for demonstrating and testing +/// the `AdaptivePrimaryButton` widget. It leverages Widgetbook +/// knobs to provide dynamic control over the +/// button's properties and state. +/// +/// ### Usage: +/// +/// This use case allows users to interactively customize and preview +/// the `AdaptivePrimaryButton` widget's behavior and appearance by +/// adjusting its properties using Widgetbook knobs. +/// +/// ### Knobs: +/// +/// - **[Request State]**: +/// - Type: `RequestStateEnum` +/// - Options: `loaded`, `loading`, etc. (all values from `RequestStateEnum`). +/// - Controls the current state of the button (e.g., disabled when `loading`). +/// - Default: `loaded`. +/// +/// - **[Button Text]**: +/// - Type: `String` +/// - Allows customization of the text displayed on the button. +/// - Default: `'Click Me'`. +/// +/// - **[Disabled]**: +/// - Type: `Boolean` +/// - Toggles the enabled/disabled state of the button. +/// - Default: `false`. +/// @UseCase( name: 'Adaptive Primary Button with Knobs', type: AdaptivePrimaryButton) diff --git a/lib/src/features/widgets/buttons/adaptive_secondary_button/adaptive_secondary_button.dart b/lib/src/features/widgets/buttons/adaptive_secondary_button/adaptive_secondary_button.dart index a0c2f6f..a4c04bd 100644 --- a/lib/src/features/widgets/buttons/adaptive_secondary_button/adaptive_secondary_button.dart +++ b/lib/src/features/widgets/buttons/adaptive_secondary_button/adaptive_secondary_button.dart @@ -3,6 +3,30 @@ import 'package:pactus_gui_widgetbook/app_styles.dart'; import 'package:pactus_gui_widgetbook/src/core/enum/request_state_enum.dart'; import 'package:pactus_gui_widgetbook/src/core/pallets/colors/app_colors.dart'; import 'package:pactus_gui_widgetbook/src/features/widgets/buttons/core/common/widgets/adaptive_button_content_widget.dart'; +/// ## [AdaptiveSecondaryButton] Class Documentation +/// +/// The `AdaptiveSecondaryButton` class is a customizable widget designed +/// for secondary actions. It features dynamic styling and behavior +/// based on its state and integrates with Fluent UI themes. +/// +/// ### Usage: +/// +/// This button provides a consistent secondary action style, allowing +/// developers to customize its text, callback action, +/// and state through its properties. +/// +/// ### Properties: +/// +/// - **[title]** (String): +/// - The text label displayed on the button. +/// +/// - **[onPressed]** (VoidCallback?): +/// - The callback function triggered when the button is pressed. +/// - Disabled if the `requestState` is `RequestStateEnum.loading`. +/// +/// - **[requestState]** (RequestStateEnum): +/// - Represents the current state of the button (e.g., loading, loaded). +/// class AdaptiveSecondaryButton extends StatelessWidget { const AdaptiveSecondaryButton({ diff --git a/lib/src/features/widgets/buttons/adaptive_secondary_button/adaptive_secondary_button_usecase.dart b/lib/src/features/widgets/buttons/adaptive_secondary_button/adaptive_secondary_button_usecase.dart index 07ae2db..15494b8 100644 --- a/lib/src/features/widgets/buttons/adaptive_secondary_button/adaptive_secondary_button_usecase.dart +++ b/lib/src/features/widgets/buttons/adaptive_secondary_button/adaptive_secondary_button_usecase.dart @@ -3,6 +3,37 @@ import 'package:pactus_gui_widgetbook/src/core/enum/request_state_enum.dart'; import 'package:pactus_gui_widgetbook/src/features/widgets/buttons/adaptive_secondary_button/adaptive_secondary_button.dart'; import 'package:widgetbook/widgetbook.dart'; import 'package:widgetbook_annotation/widgetbook_annotation.dart'; +/// ## [adaptiveSecondaryButtonUseCase] Function Documentation +/// +/// The `adaptiveSecondaryButtonUseCase` function demonstrates the +/// `AdaptiveSecondaryButton` widget in Widgetbook. It provides +/// interactive controls (knobs) for customizing the button's +/// properties and behavior during previews. +/// +/// ### Usage: +/// +/// This use case allows real-time customization of +/// the `AdaptiveSecondaryButton` widget via knobs for +/// properties such as text, request state, and enabled/disabled state. +/// +/// ### Knobs: +/// +/// - **[Request State]**: +/// - Type: `RequestStateEnum` +/// - Options: `loaded`, `loading`, etc. (all values from `RequestStateEnum`). +/// - Controls the current state of the button (e.g., disabled when `loading`). +/// - Default: `loaded`. +/// +/// - **[Button Text]**: +/// - Type: `String` +/// - Allows customization of the text displayed on the button. +/// - Default: `'Click Me'`. +/// +/// - **[Disabled]**: +/// - Type: `Boolean` +/// - Toggles the enabled/disabled state of the button. +/// - Default: `false`. + @UseCase( name: 'Adaptive Secondary Button with Knobs', type: AdaptiveSecondaryButton) diff --git a/lib/src/features/widgets/buttons/core/common/widgets/adaptive_button_content_widget.dart b/lib/src/features/widgets/buttons/core/common/widgets/adaptive_button_content_widget.dart index b6733aa..a5760ff 100644 --- a/lib/src/features/widgets/buttons/core/common/widgets/adaptive_button_content_widget.dart +++ b/lib/src/features/widgets/buttons/core/common/widgets/adaptive_button_content_widget.dart @@ -1,6 +1,30 @@ import 'package:fluent_ui/fluent_ui.dart'; import 'package:pactus_gui_widgetbook/app_styles.dart'; import 'package:pactus_gui_widgetbook/src/core/enum/request_state_enum.dart'; +/// ## [AdaptiveButtonContentWidget] Class Documentation +/// +/// The `AdaptiveButtonContentWidget` is a stateless widget responsible for +/// rendering the content of adaptive buttons. It adjusts its display based +/// on the provided `requestState`. +/// +/// ### Usage: +/// +/// This widget is typically used inside adaptive button components +/// (`AdaptivePrimaryButton`, `AdaptiveSecondaryButton`) to dynamically +/// render the button's content depending on its state. +/// +/// ### Properties: +/// +/// - **[title]** (String): +/// - The text to display on the button when the state is +/// `RequestStateEnum.loaded` or `RequestStateEnum.initial`. +/// +/// - **[requestState]** (RequestStateEnum): +/// - Determines the content of the button: +/// - `loading`: Displays an empty widget (placeholder for future loading UI). +/// - `initial`/`loaded`: Displays the button title centered inside the button. +/// - `error`: Displays an empty widget (placeholder for future error UI). +/// class AdaptiveButtonContentWidget extends StatelessWidget { const AdaptiveButtonContentWidget({ From 2de268fdf405298557ed5ba55e69c58e233d1bff Mon Sep 17 00:00:00 2001 From: PouriaMoradi021 Date: Fri, 17 Jan 2025 15:05:48 +0330 Subject: [PATCH 6/6] style: reformat code with dart reformat command --- lib/src/core/theme/app_theme_data.dart | 1 + .../adaptive_primary_button.dart | 1 + .../adaptive_primary_button_usecase.dart | 1 + .../adaptive_secondary_button.dart | 1 + .../adaptive_secondary_button_usecase.dart | 2 +- .../common/widgets/adaptive_button_content_widget.dart | 1 + .../adaptive_primary_button_test.dart | 10 ++++++---- .../adaptive_secondary_button_test.dart | 9 ++++++--- 8 files changed, 18 insertions(+), 8 deletions(-) diff --git a/lib/src/core/theme/app_theme_data.dart b/lib/src/core/theme/app_theme_data.dart index 32c7ccc..d12c1e7 100644 --- a/lib/src/core/theme/app_theme_data.dart +++ b/lib/src/core/theme/app_theme_data.dart @@ -2,6 +2,7 @@ import 'package:fluent_ui/fluent_ui.dart'; import 'package:pactus_gui_widgetbook/src/core/pallets/on_surface_pallet.dart'; import 'package:pactus_gui_widgetbook/src/core/pallets/surface_pallet.dart'; import 'package:pactus_gui_widgetbook/src/core/text_styles/inter_text_styles.dart'; + /// ## [AppThemeData] Class Documentation /// /// The `AppThemeData` class defines the theme settings for the application, diff --git a/lib/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button.dart b/lib/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button.dart index 393821b..ee7db6a 100644 --- a/lib/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button.dart +++ b/lib/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button.dart @@ -2,6 +2,7 @@ import 'package:fluent_ui/fluent_ui.dart'; import 'package:pactus_gui_widgetbook/app_styles.dart'; import 'package:pactus_gui_widgetbook/src/core/enum/request_state_enum.dart'; import 'package:pactus_gui_widgetbook/src/features/widgets/buttons/core/common/widgets/adaptive_button_content_widget.dart'; + /// ## [AdaptivePrimaryButton] Class Documentation /// /// The AdaptivePrimaryButton class is a reusable widget for creating diff --git a/lib/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button_usecase.dart b/lib/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button_usecase.dart index 0d604e0..8d72a53 100644 --- a/lib/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button_usecase.dart +++ b/lib/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button_usecase.dart @@ -3,6 +3,7 @@ import 'package:pactus_gui_widgetbook/src/core/enum/request_state_enum.dart'; import 'package:pactus_gui_widgetbook/src/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button.dart'; import 'package:widgetbook/widgetbook.dart'; import 'package:widgetbook_annotation/widgetbook_annotation.dart'; + /// ## [adaptivePrimaryButtonUseCase] Function Documentation /// /// The `adaptivePrimaryButtonUseCase` function is a Widgetbook diff --git a/lib/src/features/widgets/buttons/adaptive_secondary_button/adaptive_secondary_button.dart b/lib/src/features/widgets/buttons/adaptive_secondary_button/adaptive_secondary_button.dart index a4c04bd..0b3f304 100644 --- a/lib/src/features/widgets/buttons/adaptive_secondary_button/adaptive_secondary_button.dart +++ b/lib/src/features/widgets/buttons/adaptive_secondary_button/adaptive_secondary_button.dart @@ -3,6 +3,7 @@ import 'package:pactus_gui_widgetbook/app_styles.dart'; import 'package:pactus_gui_widgetbook/src/core/enum/request_state_enum.dart'; import 'package:pactus_gui_widgetbook/src/core/pallets/colors/app_colors.dart'; import 'package:pactus_gui_widgetbook/src/features/widgets/buttons/core/common/widgets/adaptive_button_content_widget.dart'; + /// ## [AdaptiveSecondaryButton] Class Documentation /// /// The `AdaptiveSecondaryButton` class is a customizable widget designed diff --git a/lib/src/features/widgets/buttons/adaptive_secondary_button/adaptive_secondary_button_usecase.dart b/lib/src/features/widgets/buttons/adaptive_secondary_button/adaptive_secondary_button_usecase.dart index 15494b8..b21d308 100644 --- a/lib/src/features/widgets/buttons/adaptive_secondary_button/adaptive_secondary_button_usecase.dart +++ b/lib/src/features/widgets/buttons/adaptive_secondary_button/adaptive_secondary_button_usecase.dart @@ -3,6 +3,7 @@ import 'package:pactus_gui_widgetbook/src/core/enum/request_state_enum.dart'; import 'package:pactus_gui_widgetbook/src/features/widgets/buttons/adaptive_secondary_button/adaptive_secondary_button.dart'; import 'package:widgetbook/widgetbook.dart'; import 'package:widgetbook_annotation/widgetbook_annotation.dart'; + /// ## [adaptiveSecondaryButtonUseCase] Function Documentation /// /// The `adaptiveSecondaryButtonUseCase` function demonstrates the @@ -34,7 +35,6 @@ import 'package:widgetbook_annotation/widgetbook_annotation.dart'; /// - Toggles the enabled/disabled state of the button. /// - Default: `false`. - @UseCase( name: 'Adaptive Secondary Button with Knobs', type: AdaptiveSecondaryButton) Widget adaptiveSecondaryButtonUseCase(BuildContext context) { diff --git a/lib/src/features/widgets/buttons/core/common/widgets/adaptive_button_content_widget.dart b/lib/src/features/widgets/buttons/core/common/widgets/adaptive_button_content_widget.dart index a5760ff..fa5256d 100644 --- a/lib/src/features/widgets/buttons/core/common/widgets/adaptive_button_content_widget.dart +++ b/lib/src/features/widgets/buttons/core/common/widgets/adaptive_button_content_widget.dart @@ -1,6 +1,7 @@ import 'package:fluent_ui/fluent_ui.dart'; import 'package:pactus_gui_widgetbook/app_styles.dart'; import 'package:pactus_gui_widgetbook/src/core/enum/request_state_enum.dart'; + /// ## [AdaptiveButtonContentWidget] Class Documentation /// /// The `AdaptiveButtonContentWidget` is a stateless widget responsible for diff --git a/test/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button_test.dart b/test/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button_test.dart index a63255b..4cfa134 100644 --- a/test/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button_test.dart +++ b/test/features/widgets/buttons/adaptive_primary_button/adaptive_primary_button_test.dart @@ -36,7 +36,8 @@ void main() { ); } - testWidgets('renders correctly and is clickable when loaded', (WidgetTester tester) async { + testWidgets('renders correctly and is clickable when loaded', + (WidgetTester tester) async { const testTitle = 'Test Button'; final themeWithAccent = AppThemeData.lightTheme(const Color(0xFF0A4D7E)); @@ -60,7 +61,8 @@ void main() { expect(wasPressed, isTrue); }); - testWidgets('renders correctly and is disabled when loading', (WidgetTester tester) async { + testWidgets('renders correctly and is disabled when loading', + (WidgetTester tester) async { const testTitle = 'Loading Button'; final themeWithAccent = AppThemeData.lightTheme(const Color(0xFF0A4D7E)); @@ -85,8 +87,8 @@ void main() { expect(wasPressed, isFalse); }); - - testWidgets('renders correctly with dark theme', (WidgetTester tester) async { + testWidgets('renders correctly with dark theme', + (WidgetTester tester) async { const testTitle = 'Dark Theme Button'; final themeWithAccent = AppThemeData.darkTheme(const Color(0xFF0F6CBD)); diff --git a/test/features/widgets/buttons/adaptive_secondary_button/adaptive_secondary_button_test.dart b/test/features/widgets/buttons/adaptive_secondary_button/adaptive_secondary_button_test.dart index cb51844..f349d29 100644 --- a/test/features/widgets/buttons/adaptive_secondary_button/adaptive_secondary_button_test.dart +++ b/test/features/widgets/buttons/adaptive_secondary_button/adaptive_secondary_button_test.dart @@ -36,7 +36,8 @@ void main() { ); } - testWidgets('renders correctly and is clickable when loaded', (WidgetTester tester) async { + testWidgets('renders correctly and is clickable when loaded', + (WidgetTester tester) async { const testTitle = 'Test Button'; final themeWithAccent = AppThemeData.lightTheme(const Color(0xFF0A4D7E)); @@ -60,7 +61,8 @@ void main() { expect(wasPressed, isTrue); }); - testWidgets('renders correctly and is disabled when loading', (WidgetTester tester) async { + testWidgets('renders correctly and is disabled when loading', + (WidgetTester tester) async { const testTitle = 'Loading Button'; final themeWithAccent = AppThemeData.lightTheme(const Color(0xFF0A4D7E)); @@ -85,7 +87,8 @@ void main() { expect(wasPressed, isFalse); }); - testWidgets('renders correctly with dark theme', (WidgetTester tester) async { + testWidgets('renders correctly with dark theme', + (WidgetTester tester) async { const testTitle = 'Dark Theme Button'; final themeWithAccent = AppThemeData.darkTheme(const Color(0xFF0F6CBD));