feat(ui_kit): implement top nav bar
continuous-integration/drone/push Build is passing

This commit was merged in pull request #155.
This commit is contained in:
2023-02-22 17:43:42 +01:00
parent 317eb56d66
commit 4a3fde3a1e
17 changed files with 348 additions and 80 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

@@ -61,6 +61,28 @@ class Bars extends DemoPage {
)
],
),
const Gap(20),
TopNavigationBar(
leading: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Image.asset('assets/images/studio_long_logo.png'),
),
actions: [
Padding(
padding:
const EdgeInsets.symmetric(horizontal: 20, vertical: 25),
child: FlatButton(
label: 'Estimer mon projet'.wrap(),
),
),
],
navigationItems: [
'ACCEUIL'.wrap(),
'VOTRE PROGRAMME'.wrap(),
'LE STUDIO'.wrap(),
'SAVOIR FAIRE'.wrap()
].whereType<TextWrapper>().toList(),
),
],
);
@@ -25,7 +25,7 @@ import 'package:wyatt_ui_kit_example/theme/rich_text_builder_theme.dart';
import 'package:wyatt_ui_kit_example/theme/simple_icon_button_theme.dart';
import 'package:wyatt_ui_kit_example/theme/symbol_button_theme.dart';
import 'package:wyatt_ui_kit_example/theme/text_input_theme.dart';
import 'package:wyatt_ui_kit_example/theme/top_app_bar_theme.dart';
import 'package:wyatt_ui_kit_example/theme/top_bar_theme.dart';
/// Easely switch between Material and Studio themes.
abstract class Themes {
@@ -3,24 +3,31 @@ import 'package:google_fonts/google_fonts.dart';
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/wyatt_ui_kit.dart';
class TopAppBarTheme extends TopAppBarThemeExtension {
class TopAppBarTheme extends TopBarThemeExtension {
const TopAppBarTheme({
super.iconTheme,
super.backgroundColors,
super.expandedDividerStyle,
super.secondaryColor,
super.titleStyle,
super.subTitleStyle,
});
factory TopAppBarTheme.light() => TopAppBarTheme(
backgroundColors: const MultiColor.single(
Color.fromRGBO(246, 246, 246, 1),
),
expandedDividerStyle: Colors.black.withOpacity(0.1),
secondaryColor: const Color.fromRGBO(36, 38, 42, 1),
titleStyle: GoogleFonts.montserrat(
fontWeight: FontWeight.bold,
color: const Color.fromRGBO(36, 38, 42, 1),
fontSize: 18,
),
iconTheme: const IconThemeData(color: Colors.black),
subTitleStyle: GoogleFonts.montserrat(
fontWeight: FontWeight.w400,
color: const Color.fromRGBO(36, 38, 42, 1),
fontSize: 18,
),
iconTheme: const IconThemeData(color: Color.fromRGBO(36, 38, 42, 1)),
);
factory TopAppBarTheme.dark() => TopAppBarTheme(
@@ -29,31 +36,35 @@ class TopAppBarTheme extends TopAppBarThemeExtension {
Color.fromRGBO(39, 47, 61, 1),
Color.fromRGBO(44, 50, 56, 1),
]),
expandedDividerStyle: Colors.white.withOpacity(0.1),
secondaryColor: Colors.white,
titleStyle: GoogleFonts.montserrat(
fontWeight: FontWeight.bold,
fontSize: 18,
),
subTitleStyle: GoogleFonts.montserrat(
fontWeight: FontWeight.w400,
fontSize: 18,
),
iconTheme: const IconThemeData(color: Colors.white),
);
@override
ThemeExtension<TopAppBarThemeExtension> copyWith({
ThemeExtension<TopBarThemeExtension> copyWith({
IconThemeData? iconTheme,
MultiColor? backgroundColors,
Color? expandedDividerStyle,
Color? secondaryColor,
TextStyle? titleStyle,
}) =>
TopAppBarTheme(
iconTheme: iconTheme ?? this.iconTheme,
backgroundColors: backgroundColors ?? this.backgroundColors,
expandedDividerStyle: expandedDividerStyle ?? this.expandedDividerStyle,
secondaryColor: secondaryColor ?? this.secondaryColor,
titleStyle: titleStyle ?? this.titleStyle,
);
@override
ThemeExtension<TopAppBarThemeExtension> lerp(
covariant ThemeExtension<TopAppBarThemeExtension>? other,
ThemeExtension<TopBarThemeExtension> lerp(
covariant ThemeExtension<TopBarThemeExtension>? other,
double t,
) {
if (other is! TopAppBarTheme) {
@@ -63,8 +74,7 @@ class TopAppBarTheme extends TopAppBarThemeExtension {
iconTheme: IconThemeData.lerp(iconTheme, other.iconTheme, t),
backgroundColors:
MultiColor.lerp(backgroundColors, other.backgroundColors, t),
expandedDividerStyle:
Color.lerp(expandedDividerStyle, other.expandedDividerStyle, t),
secondaryColor: Color.lerp(secondaryColor, other.secondaryColor, t),
titleStyle: TextStyle.lerp(titleStyle, other.titleStyle, t),
);
}
@@ -14,4 +14,5 @@
// You should have received a copy of the GNU General Public License
// along with super program. If not, see <https://www.gnu.org/licenses/>.
export 'top_app_bar.dart';
export './top_app_bar.dart';
export './top_navigation_bar.dart';
@@ -24,6 +24,8 @@ part 'top_app_bar.g.dart';
@ComponentCopyWithExtension()
class TopAppBar extends TopAppBarComponent with $TopAppBarCWMixin {
const TopAppBar({
super.title,
super.centerTitle,
super.systemOverlayStyle,
super.automaticallyImplyLeading,
super.flexibleSpace,
@@ -38,10 +40,8 @@ class TopAppBar extends TopAppBarComponent with $TopAppBarCWMixin {
super.excludeHeaderSemantics,
super.toolbarHeight,
super.leadingWidth,
super.title,
super.leading,
super.actions,
super.centerTitle,
super.shape,
super.expandedWidget,
super.key,
@@ -53,9 +53,7 @@ class TopAppBar extends TopAppBarComponent with $TopAppBarCWMixin {
gradient: ThemeHelper.getThemeElement<MultiColor, Gradient>(
[
backgroundColor,
context
.themeExtension<TopAppBarThemeExtension>()
?.backgroundColors,
context.themeExtension<TopBarThemeExtension>()?.backgroundColors,
],
valueValidator: (value) => value?.isGradient,
transform: (value) =>
@@ -65,9 +63,7 @@ class TopAppBar extends TopAppBarComponent with $TopAppBarCWMixin {
color: ThemeHelper.getThemeElement<MultiColor, Color>(
[
backgroundColor,
context
.themeExtension<TopAppBarThemeExtension>()
?.backgroundColors,
context.themeExtension<TopBarThemeExtension>()?.backgroundColors,
],
valueValidator: (value) => value?.isColor,
transform: (value) => value?.color,
@@ -91,7 +87,7 @@ class TopAppBar extends TopAppBarComponent with $TopAppBarCWMixin {
ThemeHelper.getThemeElement<IconThemeData, IconThemeData>(
[
iconTheme,
context.themeExtension<TopAppBarThemeExtension>()?.iconTheme,
context.themeExtension<TopBarThemeExtension>()?.iconTheme,
],
valueValidator: (value) => value != null,
transform: (value) => value,
@@ -105,9 +101,7 @@ class TopAppBar extends TopAppBarComponent with $TopAppBarCWMixin {
style: ThemeHelper.getThemeElement<TextStyle, TextStyle>(
[
title?.style,
context
.themeExtension<TopAppBarThemeExtension>()
?.titleStyle
context.themeExtension<TopBarThemeExtension>()?.titleStyle
],
valueValidator: (value) => value != null,
transform: (value) => value,
@@ -123,8 +117,9 @@ class TopAppBar extends TopAppBarComponent with $TopAppBarCWMixin {
color: ThemeHelper.getThemeElement<Color, Color>(
[
context
.themeExtension<TopAppBarThemeExtension>()
?.expandedDividerStyle,
.themeExtension<TopBarThemeExtension>()
?.secondaryColor
?.withOpacity(0.1),
],
valueValidator: (value) => value != null,
transform: (value) => value,
@@ -86,6 +86,8 @@ class $TopAppBarCWProxyImpl implements $TopAppBarComponentCWProxy {
Key? key,
}) =>
TopAppBar(
title: title ?? _value.title,
centerTitle: centerTitle ?? _value.centerTitle,
systemOverlayStyle: systemOverlayStyle ?? _value.systemOverlayStyle,
automaticallyImplyLeading:
automaticallyImplyLeading ?? _value.automaticallyImplyLeading,
@@ -103,10 +105,8 @@ class $TopAppBarCWProxyImpl implements $TopAppBarComponentCWProxy {
excludeHeaderSemantics ?? _value.excludeHeaderSemantics,
toolbarHeight: toolbarHeight ?? _value.toolbarHeight,
leadingWidth: leadingWidth ?? _value.leadingWidth,
title: title ?? _value.title,
leading: leading ?? _value.leading,
actions: actions ?? _value.actions,
centerTitle: centerTitle ?? _value.centerTitle,
shape: shape ?? _value.shape,
expandedWidget: expandedWidget ?? _value.expandedWidget,
key: key ?? _value.key,
@@ -0,0 +1,135 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:wyatt_component_copy_with_extension/component_copy_with_extension.dart';
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/src/components/bars/widgets/navigation_item.dart';
import 'package:wyatt_ui_kit/wyatt_ui_kit.dart';
part 'top_navigation_bar.g.dart';
@ComponentCopyWithExtension()
class TopNavigationBar extends TopNavigationBarComponent
with $TopNavigationBarCWMixin {
const TopNavigationBar({
super.navigationItems,
super.onTap,
super.currentIndex = 0,
super.systemOverlayStyle,
super.automaticallyImplyLeading,
super.flexibleSpace,
super.bottom,
super.elevation,
super.scrolledUnderElevation,
super.shadowColor,
super.surfaceTintColor,
super.backgroundColor,
super.iconTheme,
super.primary,
super.excludeHeaderSemantics,
super.toolbarHeight,
super.leadingWidth,
super.leading,
super.actions,
super.shape,
super.expandedWidget,
super.key,
});
@override
Widget build(BuildContext context) => DecoratedBox(
decoration: BoxDecoration(
gradient: ThemeHelper.getThemeElement<MultiColor, Gradient>(
[
backgroundColor,
context.themeExtension<TopBarThemeExtension>()?.backgroundColors,
],
valueValidator: (value) => value?.isGradient,
transform: (value) =>
LinearGradientHelper.fromNullableColors(value?.colors),
defaultValue: null,
),
color: ThemeHelper.getThemeElement<MultiColor, Color>(
[
backgroundColor,
context.themeExtension<TopBarThemeExtension>()?.backgroundColors,
],
valueValidator: (value) => value?.isColor,
transform: (value) => value?.color,
defaultValue: Theme.of(context).appBarTheme.backgroundColor,
),
),
child: AppBar(
toolbarHeight: 100,
titleSpacing: 0,
backgroundColor: Colors.transparent,
systemOverlayStyle: systemOverlayStyle,
automaticallyImplyLeading: automaticallyImplyLeading ?? true,
flexibleSpace: flexibleSpace,
bottom: bottom,
elevation: elevation ?? 0,
scrolledUnderElevation: scrolledUnderElevation,
shadowColor: shadowColor,
surfaceTintColor: surfaceTintColor,
iconTheme: ThemeHelper.getThemeElement<IconThemeData, IconThemeData>(
[
iconTheme,
context.themeExtension<TopBarThemeExtension>()?.iconTheme,
],
valueValidator: (value) => value != null,
transform: (value) => value,
defaultValue: Theme.of(context).iconTheme,
),
primary: primary ?? true,
excludeHeaderSemantics: excludeHeaderSemantics ?? false,
leadingWidth: 200,
title: Row(
mainAxisSize: MainAxisSize.min,
children: navigationItems != null
? navigationItems!
.asMap()
.map<int, Widget>(
(key, value) => MapEntry(
key,
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: MouseRegion(
cursor: SystemMouseCursors.click,
child: GestureDetector(
onTap: () {
onTap?.call(context, key);
},
child: NavigationItem(
item: value,
selected: key == currentIndex,
),
),
),
),
),
)
.values
.toList()
: [],
),
leading: leading,
actions: actions,
centerTitle: true,
),
);
}
@@ -11,6 +11,9 @@ class $TopNavigationBarCWProxyImpl
const $TopNavigationBarCWProxyImpl(this._value);
final TopNavigationBar _value;
@override
TopNavigationBar navigationItems(List<TextWrapper>? navigationItems) =>
this(navigationItems: navigationItems);
@override
TopNavigationBar onTap(void Function(BuildContext, int)? onTap) =>
this(onTap: onTap);
@override
@@ -69,6 +72,7 @@ class $TopNavigationBarCWProxyImpl
TopNavigationBar key(Key? key) => this(key: key);
@override
TopNavigationBar call({
List<TextWrapper>? navigationItems,
void Function(BuildContext, int)? onTap,
int? currentIndex,
ShapeBorder? shape,
@@ -92,10 +96,30 @@ class $TopNavigationBarCWProxyImpl
Key? key,
}) =>
TopNavigationBar(
leading: leading ?? _value.leading,
actions: actions ?? _value.actions,
navigationItems: navigationItems ?? _value.navigationItems,
onTap: onTap ?? _value.onTap,
currentIndex: currentIndex ?? _value.currentIndex,
systemOverlayStyle: systemOverlayStyle ?? _value.systemOverlayStyle,
automaticallyImplyLeading:
automaticallyImplyLeading ?? _value.automaticallyImplyLeading,
flexibleSpace: flexibleSpace ?? _value.flexibleSpace,
bottom: bottom ?? _value.bottom,
elevation: elevation ?? _value.elevation,
scrolledUnderElevation:
scrolledUnderElevation ?? _value.scrolledUnderElevation,
shadowColor: shadowColor ?? _value.shadowColor,
surfaceTintColor: surfaceTintColor ?? _value.surfaceTintColor,
backgroundColor: backgroundColor ?? _value.backgroundColor,
iconTheme: iconTheme ?? _value.iconTheme,
primary: primary ?? _value.primary,
excludeHeaderSemantics:
excludeHeaderSemantics ?? _value.excludeHeaderSemantics,
toolbarHeight: toolbarHeight ?? _value.toolbarHeight,
leadingWidth: leadingWidth ?? _value.leadingWidth,
leading: leading ?? _value.leading,
actions: actions ?? _value.actions,
shape: shape ?? _value.shape,
expandedWidget: expandedWidget ?? _value.expandedWidget,
key: key ?? _value.key,
);
}
@@ -0,0 +1,73 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// super program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// super program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with super program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/wyatt_ui_kit.dart';
class NavigationItem extends StatelessWidget {
const NavigationItem({
required this.item,
required this.selected,
super.key,
});
final TextWrapper item;
final bool selected;
@override
Widget build(BuildContext context) => Stack(
alignment: Alignment.bottomCenter,
children: [
if (selected)
Container(
height: 5,
width: 70,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(100),
color: ThemeHelper.getThemeElement<Color, Color>(
[
context
.themeExtension<TopBarThemeExtension>()
?.secondaryColor
],
valueValidator: (value) => value != null,
transform: (value) => value,
defaultValue: Theme.of(context).primaryColor,
),
),
),
SizedBox(
height: 50,
child: Center(
child: Text(
item.data,
style: ThemeHelper.getThemeElement<TextStyle, TextStyle>(
[
item.style,
context
.themeExtension<TopBarThemeExtension>()
?.subTitleStyle
],
valueValidator: (value) => value != null,
transform: (value) => value,
defaultValue: context.textTheme.titleMedium,
),
),
),
),
],
);
}
@@ -14,10 +14,10 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
export './app_bars/app_bars.dart';
export './buttons/buttons.dart';
export './cards/cards.dart';
export './gradients/gradients.dart';
export './loader/loader.dart';
export './rich_text_builder/rich_text_builder.dart';
export './text_inputs/text_input.dart';
export 'bars/bars.dart';
@@ -1,35 +0,0 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import 'package:wyatt_component_copy_with_extension/component_copy_with_extension.dart';
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
part 'top_navigation_bar.g.dart';
@ComponentCopyWithExtension()
class TopNavigationBar extends TopNavigationBarComponent
with $TopNavigationBarCWMixin {
const TopNavigationBar({
super.leading,
super.actions,
super.onTap,
super.currentIndex = 0,
super.key,
});
@override
Widget build(BuildContext context) => const Placeholder();
}
@@ -19,4 +19,4 @@ export './card_theme_extension.dart';
export './loader_theme_extension.dart';
export './rich_text_builder_theme_extension.dart';
export './text_input_theme_extension.dart';
export './top_app_bar_extension.dart';
export 'top_bar_theme_extension.dart';
@@ -17,18 +17,20 @@
import 'package:flutter/material.dart';
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
abstract class TopAppBarThemeExtension
extends ThemeExtension<TopAppBarThemeExtension> {
const TopAppBarThemeExtension({
abstract class TopBarThemeExtension
extends ThemeExtension<TopBarThemeExtension> {
const TopBarThemeExtension({
this.iconTheme,
this.backgroundColors,
this.expandedDividerStyle,
this.secondaryColor,
this.titleStyle,
this.subTitleStyle,
});
final MultiColor? backgroundColors;
final IconThemeData? iconTheme;
final Color? expandedDividerStyle;
final Color? secondaryColor;
final TextStyle? titleStyle;
final TextStyle? subTitleStyle;
}