diff --git a/example/lib/home.dart b/example/lib/home.dart index 0ff969ac..e70e2b66 100644 --- a/example/lib/home.dart +++ b/example/lib/home.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:zeta_example/pages/components/accordion_example.dart'; -import 'package:zeta_example/pages/components/app_bar_example.dart'; +import 'package:zeta_example/pages/components/top_app_bar_example.dart'; import 'package:zeta_example/pages/components/avatar_example.dart'; import 'package:zeta_example/pages/components/badges_example.dart'; import 'package:zeta_example/pages/components/banner_example.dart'; diff --git a/example/lib/pages/components/app_bar_example.dart b/example/lib/pages/components/top_app_bar_example.dart similarity index 96% rename from example/lib/pages/components/app_bar_example.dart rename to example/lib/pages/components/top_app_bar_example.dart index 250bc8a7..64402289 100644 --- a/example/lib/pages/components/app_bar_example.dart +++ b/example/lib/pages/components/top_app_bar_example.dart @@ -7,7 +7,7 @@ import 'package:zeta_flutter/zeta_flutter.dart'; class AppBarExample extends StatefulWidget { const AppBarExample({super.key}); - static const String name = 'AppBar'; + static const String name = 'Top App Bar'; @override State createState() => _AppBarExampleState(); @@ -30,7 +30,7 @@ class _AppBarExampleState extends State { // Default Padding( padding: const EdgeInsets.only(top: ZetaSpacing.x4), - child: ZetaAppBar( + child: ZetaTopAppBar( leading: IconButton( onPressed: () {}, icon: Icon(Icons.menu_rounded), @@ -64,7 +64,7 @@ class _AppBarExampleState extends State { // Centered Padding( padding: const EdgeInsets.only(top: ZetaSpacing.x4), - child: ZetaAppBar( + child: ZetaTopAppBar( type: ZetaAppBarType.centeredTitle, leading: IconButton( onPressed: () {}, @@ -83,7 +83,7 @@ class _AppBarExampleState extends State { // Contextual Padding( padding: const EdgeInsets.only(top: ZetaSpacing.x4), - child: ZetaAppBar( + child: ZetaTopAppBar( leading: IconButton( onPressed: () {}, icon: Icon(ZetaIcons.close_round), @@ -115,7 +115,7 @@ class _AppBarExampleState extends State { padding: const EdgeInsets.only(top: ZetaSpacing.x4), child: Column( children: [ - ZetaAppBar( + ZetaTopAppBar( type: ZetaAppBarType.centeredTitle, leading: BackButton(), title: Text("Title"), @@ -151,7 +151,7 @@ class _AppBarExampleState extends State { // Extended Padding( padding: const EdgeInsets.only(top: ZetaSpacing.x4), - child: ZetaAppBar( + child: ZetaTopAppBar( type: ZetaAppBarType.extendedTitle, leading: IconButton( onPressed: () {}, diff --git a/example/widgetbook/main.dart b/example/widgetbook/main.dart index 2b38a3e9..bcf9a65e 100644 --- a/example/widgetbook/main.dart +++ b/example/widgetbook/main.dart @@ -4,7 +4,7 @@ import 'package:zeta_flutter/zeta_flutter.dart'; import 'pages/assets/icon_widgetbook.dart'; import 'pages/components/accordion_widgetbook.dart'; -import 'pages/components/app_bar_widgetbook.dart'; +import 'pages/components/top_app_bar_widgetbook.dart'; import 'pages/components/avatar_widgetbook.dart'; import 'pages/components/badges_widgetbook.dart'; import 'pages/components/banner_widgetbook.dart'; @@ -61,9 +61,10 @@ class HotReload extends StatelessWidget { isInitiallyExpanded: false, children: [ WidgetbookComponent( - name: 'App Bar', + name: 'Top App Bar', useCases: [ - WidgetbookUseCase(name: 'Default', builder: (context) => defaultAppBarUseCase(context)), + WidgetbookUseCase(name: 'Default', builder: (context) => defaultTopAppBarUseCase(context)), + WidgetbookUseCase(name: 'Extended', builder: (context) => extendedTopAppBarUseCase(context)), WidgetbookUseCase(name: 'Search', builder: (context) => searchAppBarUseCase(context)), ], ), diff --git a/example/widgetbook/pages/components/app_bar_widgetbook.dart b/example/widgetbook/pages/components/top_app_bar_widgetbook.dart similarity index 65% rename from example/widgetbook/pages/components/app_bar_widgetbook.dart rename to example/widgetbook/pages/components/top_app_bar_widgetbook.dart index 097cdaf1..a8e8636c 100644 --- a/example/widgetbook/pages/components/app_bar_widgetbook.dart +++ b/example/widgetbook/pages/components/top_app_bar_widgetbook.dart @@ -6,7 +6,7 @@ import 'package:zeta_flutter/zeta_flutter.dart'; import '../../test/test_components.dart'; -Widget defaultAppBarUseCase(BuildContext context) { +Widget defaultTopAppBarUseCase(BuildContext context) { return WidgetbookTestWidget( widget: StatefulBuilder( builder: (context, setState) { @@ -17,7 +17,7 @@ Widget defaultAppBarUseCase(BuildContext context) { options: [ ZetaAppBarType.defaultAppBar, ZetaAppBarType.centeredTitle, - ZetaAppBarType.extendedTitle, + // ZetaAppBarType.extendedTitle, ], initialOption: ZetaAppBarType.defaultAppBar, labelBuilder: (type) => type.name, @@ -48,7 +48,7 @@ Widget defaultAppBarUseCase(BuildContext context) { labelBuilder: (icon) => icon.key.toString(), ); - return ZetaAppBar( + return ZetaTopAppBar( leading: IconButton( onPressed: () {}, icon: leadingIcon, @@ -77,6 +77,86 @@ Widget defaultAppBarUseCase(BuildContext context) { ); } +Widget extendedTopAppBarUseCase(BuildContext context) { + return WidgetbookTestWidget(widget: LayoutBuilder(builder: (context, constraints) { + final title = context.knobs.string(label: "Title", initialValue: "Title"); + + final type = context.knobs.list( + label: "Type", + options: [ + ZetaAppBarType.defaultAppBar, + ZetaAppBarType.centeredTitle, + // ZetaAppBarType.extendedTitle, + ], + initialOption: ZetaAppBarType.defaultAppBar, + labelBuilder: (type) => type.name, + ); + + final enabledActions = context.knobs.boolean( + label: "Enabled actions", + initialValue: true, + ); + + final leadingIcon = context.knobs.list( + label: "Leading Icon", + options: [ + Icon( + key: Key("Menu"), + Icons.menu_rounded, + ), + Icon( + key: Key("Close"), + ZetaIcons.close_round, + ), + Icon( + key: Key("Arrow back"), + ZetaIcons.arrow_back_round, + ), + ], + initialOption: Icon(Icons.menu_rounded), + labelBuilder: (icon) => icon.key.toString(), + ); + + return SizedBox( + width: constraints.maxWidth, + height: 200, // constraints.maxHeight, + child: CustomScrollView( + slivers: [ + ZetaTopAppBar( + type: ZetaAppBarType.extendedTitle, + leading: IconButton( + onPressed: () {}, + icon: leadingIcon, + ), + title: Text(title), + actions: enabledActions + ? [ + IconButton( + onPressed: () {}, + icon: Icon(Icons.language), + ), + IconButton( + onPressed: () {}, + icon: Icon(Icons.favorite), + ), + IconButton( + onPressed: () {}, + icon: Icon(ZetaIcons.more_vertical_round), + ) + ] + : null, + ), + SliverFillRemaining( + child: ColoredBox( + color: Colors.green, + ), + ) + ], + ), + ); + })); +} + Widget searchAppBarUseCase(BuildContext context) { return WidgetbookTestWidget( widget: _SearchUseCase(), @@ -135,7 +215,7 @@ class _SearchUseCaseState extends State<_SearchUseCase> { initialValue: false, ); - return ZetaAppBar( + return ZetaTopAppBar( leading: IconButton( onPressed: () {}, icon: leadingIcon, diff --git a/lib/src/components/buttons/button_group.dart b/lib/src/components/buttons/button_group.dart index 1f30db8e..6c5770fd 100644 --- a/lib/src/components/buttons/button_group.dart +++ b/lib/src/components/buttons/button_group.dart @@ -41,11 +41,11 @@ class ZetaButtonGroup extends StatelessWidget { for (final (index, button) in buttons.indexed) { mappedButtons.add( button.copyWith( - large: isLarge, - inverse: isInverse, - round: rounded, - fin: index == buttons.length - 1, - initial: index == 0, + isLarge: isLarge, + isInverse: isInverse, + rounded: rounded, + isFinal: index == buttons.length - 1, + isInitial: index == 0, ), ); } @@ -153,11 +153,11 @@ class ZetaGroupButton extends StatefulWidget { /// Returns copy of [ZetaGroupButton] with fields. ZetaGroupButton copyWith({ - bool? fin, - bool? initial, - bool? large, - bool? round, - bool? inverse, + bool? isFinal, + bool? isInitial, + bool? isLarge, + bool? rounded, + bool? isInverse, }) { return ZetaGroupButton._( key: key, @@ -165,11 +165,11 @@ class ZetaGroupButton extends StatefulWidget { icon: icon, onPressed: onPressed, dropdown: dropdown, - isFinal: fin ?? isFinal, - isInitial: initial ?? isInitial, - isLarge: large ?? isLarge, - rounded: round ?? rounded, - isInverse: inverse ?? isInverse, + isFinal: isFinal ?? this.isFinal, + isInitial: isInitial ?? this.isInitial, + isLarge: isLarge ?? this.isLarge, + rounded: rounded ?? this.rounded, + isInverse: isInverse ?? this.isInverse, ); } @@ -327,11 +327,6 @@ class _ZetaGroupButtonState extends State { @override void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); - properties.add( - DiagnosticsProperty( - 'controller', - controller, - ), - ); + properties.add(DiagnosticsProperty('controller', controller)); } } diff --git a/lib/src/components/screen_header_bar/screen_header_bar.dart b/lib/src/components/screen_header_bar/screen_header_bar.dart index 6a846778..2760038f 100644 --- a/lib/src/components/screen_header_bar/screen_header_bar.dart +++ b/lib/src/components/screen_header_bar/screen_header_bar.dart @@ -27,7 +27,7 @@ class ZetaScreenHeaderBar extends StatelessWidget { @override Widget build(BuildContext context) { - return ZetaAppBar( + return ZetaTopAppBar( leading: IconButton( onPressed: () async => Navigator.maybePop(context), icon: Icon(rounded ? ZetaIcons.chevron_left_round : ZetaIcons.chevron_left_sharp), diff --git a/lib/src/components/app_bar/app_bar.dart b/lib/src/components/top_app_bar/top_app_bar.dart similarity index 86% rename from lib/src/components/app_bar/app_bar.dart rename to lib/src/components/top_app_bar/top_app_bar.dart index 158a0a3c..f63d7c95 100644 --- a/lib/src/components/app_bar/app_bar.dart +++ b/lib/src/components/top_app_bar/top_app_bar.dart @@ -2,10 +2,10 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import '../../../zeta_flutter.dart'; -/// Zeta app bar. -class ZetaAppBar extends StatefulWidget implements PreferredSizeWidget { +/// Top app bars provide content and actions related to the current screen. +class ZetaTopAppBar extends StatefulWidget implements PreferredSizeWidget { /// Creates a Zeta app bar. - const ZetaAppBar({ + const ZetaTopAppBar({ this.actions, this.automaticallyImplyLeading = true, this.searchController, @@ -20,7 +20,7 @@ class ZetaAppBar extends StatefulWidget implements PreferredSizeWidget { super.key, }); - /// Called when text in the search field is submited. + /// Called when text in the search field is submitted. final void Function(String)? onSearch; /// A list of Widgets to display in a row after the [title] widget. @@ -35,7 +35,7 @@ class ZetaAppBar extends StatefulWidget implements PreferredSizeWidget { /// If omitted the microphone icon won't show up. Called when the icon button is pressed. Normally used for speech recognition/speech to text. final VoidCallback? onSearchMicrophoneIconPressed; - /// Used to controll the search textfield and states. + /// Used to control the search textfield and states. final AppBarSearchController? searchController; /// Label used as hint text. @@ -54,7 +54,7 @@ class ZetaAppBar extends StatefulWidget implements PreferredSizeWidget { final ZetaAppBarType type; @override - State createState() => _ZetaAppBarState(); + State createState() => _ZetaTopAppBarState(); @override Size get preferredSize => const Size.fromHeight(kToolbarHeight); @@ -91,7 +91,7 @@ class ZetaAppBar extends StatefulWidget implements PreferredSizeWidget { } } -class _ZetaAppBarState extends State { +class _ZetaTopAppBarState extends State { bool _isSearchEnabled = false; @override @@ -125,7 +125,49 @@ class _ZetaAppBarState extends State { @override Widget build(BuildContext context) { final colors = Zeta.of(context).colors; - + if (widget.type == ZetaAppBarType.extendedTitle) { + return SliverAppBar( + elevation: 0, + expandedHeight: 104, + collapsedHeight: 50, + iconTheme: IconThemeData(color: colors.cool.shade90), + leading: widget.leading, + automaticallyImplyLeading: widget.automaticallyImplyLeading, + titleSpacing: 0, + titleTextStyle: widget.titleTextStyle == null + ? ZetaTextStyles.bodyLarge.copyWith( + color: colors.textDefault, + ) + : widget.titleTextStyle!.copyWith( + color: colors.textDefault, + ), + title: widget.searchController != null + ? _SearchField( + searchController: widget.searchController, + hintText: widget.searchHintText, + onSearch: widget.onSearch, + type: widget.type, + child: _getTitle(), + ) + : _getTitle(), + actions: widget.actions, + toolbarHeight: 64, + flexibleSpace: Padding( + padding: EdgeInsets.only( + top: widget.preferredSize.height, + left: ZetaSpacing.s, + right: ZetaSpacing.s, + ), + child: DefaultTextStyle( + style: ZetaTextStyles.bodyLarge.copyWith( + color: colors.textDefault, + ), + child: widget.title ?? const SizedBox(), + ), + ), + pinned: true, + ); + } return IconButtonTheme( data: IconButtonThemeData( style: IconButton.styleFrom( @@ -192,21 +234,6 @@ class _ZetaAppBarState extends State { ), ] : widget.actions, - flexibleSpace: widget.type == ZetaAppBarType.extendedTitle - ? Padding( - padding: EdgeInsets.only( - top: widget.preferredSize.height, - left: ZetaSpacing.s, - right: ZetaSpacing.s, - ), - child: DefaultTextStyle( - style: ZetaTextStyles.bodyLarge.copyWith( - color: colors.textDefault, - ), - child: widget.title ?? const SizedBox(), - ), - ) - : null, ), ), ); diff --git a/lib/zeta_flutter.dart b/lib/zeta_flutter.dart index ce453296..013c01c4 100644 --- a/lib/zeta_flutter.dart +++ b/lib/zeta_flutter.dart @@ -3,7 +3,6 @@ library zeta_flutter; export 'src/assets/icons.dart'; export 'src/components/accordion/accordion.dart'; -export 'src/components/app_bar/app_bar.dart'; export 'src/components/avatars/avatar.dart'; export 'src/components/badges/badge.dart'; export 'src/components/badges/indicator.dart'; @@ -51,6 +50,7 @@ export 'src/components/switch/zeta_switch.dart'; export 'src/components/tabs/tab.dart'; export 'src/components/tabs/tab_bar.dart'; export 'src/components/tooltip/tooltip.dart'; +export 'src/components/top_app_bar/top_app_bar.dart'; export 'src/theme/color_extensions.dart'; export 'src/theme/color_scheme.dart'; export 'src/theme/color_swatch.dart';