From e07fc482e8a4ed06a33b8aa22388456f7e1cf5fc Mon Sep 17 00:00:00 2001 From: atanasyordanov21 <63714308+atanasyordanov21@users.noreply.github.com> Date: Mon, 29 Apr 2024 18:00:44 +0300 Subject: [PATCH] feat: ZetaScreenHeaderBar (#39) --- example/lib/home.dart | 2 + .../components/screen_header_bar_example.dart | 21 +++++++ example/widgetbook/main.dart | 2 + .../screen_header_bar_widgetbook.dart | 22 +++++++ lib/src/components/app_bar/app_bar.dart | 24 ++++++-- .../screen_header_bar/screen_header_bar.dart | 58 +++++++++++++++++++ lib/zeta_flutter.dart | 1 + 7 files changed, 125 insertions(+), 5 deletions(-) create mode 100644 example/lib/pages/components/screen_header_bar_example.dart create mode 100644 example/widgetbook/pages/components/screen_header_bar_widgetbook.dart create mode 100644 lib/src/components/screen_header_bar/screen_header_bar.dart diff --git a/example/lib/home.dart b/example/lib/home.dart index 5e7db604..8d76134b 100644 --- a/example/lib/home.dart +++ b/example/lib/home.dart @@ -20,6 +20,7 @@ import 'package:zeta_example/pages/components/navigation_bar_example.dart'; import 'package:zeta_example/pages/components/navigation_rail_example.dart'; import 'package:zeta_example/pages/components/phone_input_example.dart'; import 'package:zeta_example/pages/components/radio_example.dart'; +import 'package:zeta_example/pages/components/screen_header_bar_example.dart'; import 'package:zeta_example/pages/components/select_input_example.dart'; import 'package:zeta_example/pages/components/search_bar_example.dart'; import 'package:zeta_example/pages/components/segmented_control_example.dart'; @@ -77,6 +78,7 @@ final List components = [ Component(TooltipExample.name, (context) => const TooltipExample()), Component(NavigationRailExample.name, (context) => const NavigationRailExample()), Component(SelectInputExample.name, (context) => const SelectInputExample()), + Component(ScreenHeaderBarExample.name, (context) => const ScreenHeaderBarExample()), Component(FilterSelectionExample.name, (context) => const FilterSelectionExample()), ]; diff --git a/example/lib/pages/components/screen_header_bar_example.dart b/example/lib/pages/components/screen_header_bar_example.dart new file mode 100644 index 00000000..c617db1b --- /dev/null +++ b/example/lib/pages/components/screen_header_bar_example.dart @@ -0,0 +1,21 @@ +import 'package:flutter/material.dart'; +import 'package:zeta_example/widgets.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +class ScreenHeaderBarExample extends StatelessWidget { + const ScreenHeaderBarExample({super.key}); + + static const String name = 'ScreenHeaderBar'; + + @override + Widget build(BuildContext context) { + return ExampleScaffold( + name: ScreenHeaderBarExample.name, + child: ZetaScreenHeaderBar( + title: Text("Add Subscribers"), + actionButtonLabel: 'Done', + onActionButtonPressed: () {}, + ), + ); + } +} diff --git a/example/widgetbook/main.dart b/example/widgetbook/main.dart index 28cf6e87..6d1f72fe 100644 --- a/example/widgetbook/main.dart +++ b/example/widgetbook/main.dart @@ -27,6 +27,7 @@ import 'pages/components/password_input_widgetbook.dart'; import 'pages/components/phone_input_widgetbook.dart'; import 'pages/components/progress_widgetbook.dart'; import 'pages/components/radio_widgetbook.dart'; +import 'pages/components/screen_header_bar_widgetbook.dart'; import 'pages/components/search_bar_widgetbook.dart'; import 'pages/components/segmented_control_widgetbook.dart'; import 'pages/components/select_input_widgetbook.dart'; @@ -140,6 +141,7 @@ class HotReload extends StatelessWidget { WidgetbookUseCase(name: 'Navigation Rail', builder: (context) => navigationRailUseCase(context)), WidgetbookUseCase(name: 'Tooltip', builder: (context) => tooltipUseCase(context)), WidgetbookUseCase(name: 'Select Input', builder: (context) => selectInputUseCase(context)), + WidgetbookUseCase(name: 'Screen Header Bar', builder: (context) => screenHeaderBarUseCase(context)), WidgetbookUseCase(name: 'Filter Selection', builder: (context) => filterSelectionUseCase(context)), ]..sort((a, b) => a.name.compareTo(b.name)), ), diff --git a/example/widgetbook/pages/components/screen_header_bar_widgetbook.dart b/example/widgetbook/pages/components/screen_header_bar_widgetbook.dart new file mode 100644 index 00000000..dfc66336 --- /dev/null +++ b/example/widgetbook/pages/components/screen_header_bar_widgetbook.dart @@ -0,0 +1,22 @@ +import 'package:flutter/material.dart'; +import 'package:widgetbook/widgetbook.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +import '../../test/test_components.dart'; + +Widget screenHeaderBarUseCase(BuildContext context) { + final title = context.knobs.string( + label: 'Title', + initialValue: 'Add Subscribers', + ); + final rounded = context.knobs.boolean(label: 'Rounded', initialValue: true); + + return WidgetbookTestWidget( + widget: ZetaScreenHeaderBar( + title: Text(title), + actionButtonLabel: 'Done', + onActionButtonPressed: () {}, + rounded: rounded, + ), + ); +} diff --git a/lib/src/components/app_bar/app_bar.dart b/lib/src/components/app_bar/app_bar.dart index a0debf79..5c54548f 100644 --- a/lib/src/components/app_bar/app_bar.dart +++ b/lib/src/components/app_bar/app_bar.dart @@ -11,6 +11,8 @@ class ZetaAppBar extends StatefulWidget implements PreferredSizeWidget { this.searchController, this.leading, this.title, + this.titleSpacing, + this.titleTextStyle, this.type = ZetaAppBarType.defaultAppBar, this.onSearch, this.searchHintText = 'Search', @@ -42,6 +44,12 @@ class ZetaAppBar extends StatefulWidget implements PreferredSizeWidget { /// Title of the app bar. Normally a [Text] widget. final Widget? title; + /// AppBar titleSpacing + final double? titleSpacing; + + /// AppBar titleTextStyle + final TextStyle? titleTextStyle; + /// Defines the styles of the app bar. final ZetaAppBarType type; @@ -76,7 +84,9 @@ class ZetaAppBar extends StatefulWidget implements PreferredSizeWidget { ), ) ..add(StringProperty('searchHintText', searchHintText)) - ..add(EnumProperty('type', type)); + ..add(EnumProperty('type', type)) + ..add(DoubleProperty('titleSpacing', titleSpacing)) + ..add(DiagnosticsProperty('titleTextStyle', titleTextStyle)); } } @@ -105,7 +115,7 @@ class _ZetaAppBarState extends State { Widget? _getTitle() { return widget.type != ZetaAppBarType.extendedTitle ? Padding( - padding: const EdgeInsets.symmetric(horizontal: ZetaSpacing.b), + padding: EdgeInsets.symmetric(horizontal: widget.titleSpacing ?? ZetaSpacing.b), child: widget.title, ) : null; @@ -131,9 +141,13 @@ class _ZetaAppBarState extends State { automaticallyImplyLeading: widget.automaticallyImplyLeading, centerTitle: widget.type == ZetaAppBarType.centeredTitle, titleSpacing: 0, - titleTextStyle: ZetaTextStyles.bodyLarge.copyWith( - color: colors.textDefault, - ), + titleTextStyle: widget.titleTextStyle == null + ? ZetaTextStyles.bodyLarge.copyWith( + color: colors.textDefault, + ) + : widget.titleTextStyle!.copyWith( + color: colors.textDefault, + ), title: widget.searchController != null ? _SearchField( searchController: widget.searchController, diff --git a/lib/src/components/screen_header_bar/screen_header_bar.dart b/lib/src/components/screen_header_bar/screen_header_bar.dart new file mode 100644 index 00000000..6a846778 --- /dev/null +++ b/lib/src/components/screen_header_bar/screen_header_bar.dart @@ -0,0 +1,58 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import '../../../zeta_flutter.dart'; + +/// [ZetaScreenHeaderBar] +class ZetaScreenHeaderBar extends StatelessWidget { + /// Constructor for [ZetaScreenHeaderBar]. + const ZetaScreenHeaderBar({ + this.title, + this.rounded = true, + this.actionButtonLabel, + this.onActionButtonPressed, + super.key, + }); + + /// The title of [ZetaScreenHeaderBar]. Normally a [Text] widget. + final Widget? title; + + /// {@macro zeta-component-rounded} + final bool rounded; + + /// The label of the action button. + final String? actionButtonLabel; + + /// Called when the action button is pressed. + final VoidCallback? onActionButtonPressed; + + @override + Widget build(BuildContext context) { + return ZetaAppBar( + leading: IconButton( + onPressed: () async => Navigator.maybePop(context), + icon: Icon(rounded ? ZetaIcons.chevron_left_round : ZetaIcons.chevron_left_sharp), + ), + title: title, + titleSpacing: 0, + titleTextStyle: ZetaTextStyles.titleLarge, + actions: actionButtonLabel == null + ? null + : [ + ZetaButton( + label: actionButtonLabel!, + onPressed: onActionButtonPressed, + borderType: rounded ? ZetaWidgetBorder.rounded : ZetaWidgetBorder.sharp, + ), + ], + ); + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('rounded', rounded)) + ..add(StringProperty('actionButtonLabel', actionButtonLabel)) + ..add(ObjectFlagProperty.has('onActionButtonPressed', onActionButtonPressed)); + } +} diff --git a/lib/zeta_flutter.dart b/lib/zeta_flutter.dart index e3414716..cb37ebfd 100644 --- a/lib/zeta_flutter.dart +++ b/lib/zeta_flutter.dart @@ -37,6 +37,7 @@ export 'src/components/phone_input/phone_input.dart'; export 'src/components/progress/progress_bar.dart'; export 'src/components/progress/progress_circle.dart'; export 'src/components/radio/radio.dart'; +export 'src/components/screen_header_bar/screen_header_bar.dart'; export 'src/components/search_bar/search_bar.dart'; export 'src/components/segmented_control/segmented_control.dart'; export 'src/components/select_input/select_input.dart';