From 13c491cab99e2ac826dfeb2c11ed1d250eb031c8 Mon Sep 17 00:00:00 2001 From: Hugo Pointcheval Date: Tue, 14 Feb 2023 11:54:32 +0100 Subject: [PATCH] feat(ui_kit): implement file selection button with invalid cubit and dotted package --- .../example/lib/buttons/buttons.dart | 42 +++ .../lib/src/components/buttons/buttons.dart | 1 + .../buttons/cubit/invalid_button_cubit.dart | 73 +++++ .../cubit/selectable_button_cubit.dart | 20 ++ .../file_selection_button.dart | 96 +++++++ .../file_selection_button.g.dart | 85 ++++++ .../file_selection_button_screen.dart | 251 ++++++++++++++++++ .../flat_button/flat_button_screen.dart | 205 +++++++------- packages/wyatt_ui_kit/pubspec.yaml | 1 + 9 files changed, 670 insertions(+), 104 deletions(-) create mode 100644 packages/wyatt_ui_kit/lib/src/components/buttons/cubit/invalid_button_cubit.dart create mode 100644 packages/wyatt_ui_kit/lib/src/components/buttons/file_selection_button/file_selection_button.dart create mode 100644 packages/wyatt_ui_kit/lib/src/components/buttons/file_selection_button/file_selection_button.g.dart create mode 100644 packages/wyatt_ui_kit/lib/src/components/buttons/file_selection_button/file_selection_button_screen.dart diff --git a/packages/wyatt_ui_kit/example/lib/buttons/buttons.dart b/packages/wyatt_ui_kit/example/lib/buttons/buttons.dart index f7e312e3..8d9cbd9f 100644 --- a/packages/wyatt_ui_kit/example/lib/buttons/buttons.dart +++ b/packages/wyatt_ui_kit/example/lib/buttons/buttons.dart @@ -30,6 +30,7 @@ const _background = Color(0xFF16191D); const _disabledBackground = Color(0xFF16191D + 0x66FFFFFF); const _disabledColors = [Color(0xFF60656A), Color(0xFF383C40)]; const _selectedColors = [Color(0xFF50CE99), Color(0xFF339572)]; +const _invalidColor = Color(0xFFFB5E3C); class Buttons extends StatelessWidget { const Buttons({super.key}); @@ -325,6 +326,47 @@ class Buttons extends StatelessWidget { ), ], ), + const Gap(20), + FileSelectionButton( + leading: const DecoratedBox( + decoration: BoxDecoration( + color: _disabled, + borderRadius: BorderRadius.all( + Radius.circular(5), + ), + ), + child: Padding( + padding: EdgeInsets.all(8), + child: Icon( + Icons.file_upload_outlined, + color: Colors.white, + ), + ), + ), + title: TextWrapper( + 'Ajouter un fichier', + style: Theme.of(context) + .textTheme + .titleLarge + ?.copyWith(color: _disabled), + ), + subTitle: TextWrapper.text('Taille max: 20 Mo'), + normalStyle: const FileSelectionButtonStyle( + backgroundColors: MultiColor.single(_disabledBackground), + foregroundColors: MultiColor.single(_disabled), + borderColors: MultiColor.single(_disabled), + ), + hoveredStyle: const FileSelectionButtonStyle( + backgroundColors: MultiColor.single(_disabledBackground), + foregroundColors: MultiColor.single(_disabled), + borderColors: MultiColor.single(Colors.white), + ), + invalidStyle: const FileSelectionButtonStyle( + backgroundColors: MultiColor.single(_disabledBackground), + foregroundColors: MultiColor.single(_invalidColor), + borderColors: MultiColor.single(_invalidColor), + ), + ) ], ), ), diff --git a/packages/wyatt_ui_kit/lib/src/components/buttons/buttons.dart b/packages/wyatt_ui_kit/lib/src/components/buttons/buttons.dart index c3cd55d7..bf04a627 100644 --- a/packages/wyatt_ui_kit/lib/src/components/buttons/buttons.dart +++ b/packages/wyatt_ui_kit/lib/src/components/buttons/buttons.dart @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +export './file_selection_button/file_selection_button.dart'; export './flat_button/flat_button.dart'; export './simple_icon_button/simple_icon_button.dart'; export './symbol_button/symbol_button.dart'; diff --git a/packages/wyatt_ui_kit/lib/src/components/buttons/cubit/invalid_button_cubit.dart b/packages/wyatt_ui_kit/lib/src/components/buttons/cubit/invalid_button_cubit.dart new file mode 100644 index 00000000..e90832d8 --- /dev/null +++ b/packages/wyatt_ui_kit/lib/src/components/buttons/cubit/invalid_button_cubit.dart @@ -0,0 +1,73 @@ +// 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 . + +import 'dart:async'; +import 'dart:math'; + +import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart'; +import 'package:wyatt_ui_kit/src/components/buttons/cubit/button_cubit.dart'; + +class InvalidButtonCubit extends ButtonCubit { + @override + FutureOr onClickUpIn() async { + if (state.isDisabled || state.isFreezed) { + return; + } + + emit( + state.copyWith( + state: ControlState.hovered, + // TODO(hpcl): change this + invalid: Random().nextBool(), + ), + ); + } + + @override + FutureOr onClickUpOut() async { + if (state.isDisabled || state.isFreezed) { + return; + } + + emit( + state.copyWith( + state: ControlState.normal, + // TODO(hpcl): change this + invalid: Random().nextBool(), + ), + ); + } + + FutureOr invalidate() async { + if (state.isDisabled || state.isFreezed) { + return; + } + + emit( + state.copyWith(invalid: true), + ); + } + + FutureOr fix() async { + if (state.isDisabled || state.isFreezed) { + return; + } + + emit( + state.copyWith(invalid: false), + ); + } +} diff --git a/packages/wyatt_ui_kit/lib/src/components/buttons/cubit/selectable_button_cubit.dart b/packages/wyatt_ui_kit/lib/src/components/buttons/cubit/selectable_button_cubit.dart index a271e09a..9b747ad4 100644 --- a/packages/wyatt_ui_kit/lib/src/components/buttons/cubit/selectable_button_cubit.dart +++ b/packages/wyatt_ui_kit/lib/src/components/buttons/cubit/selectable_button_cubit.dart @@ -37,4 +37,24 @@ class SelectableButtonCubit extends ButtonCubit { } emit(state.copyWith(state: ControlState.normal, selected: !state.selected)); } + + FutureOr select() async { + if (state.isDisabled || state.isFreezed) { + return; + } + + emit( + state.copyWith(selected: true), + ); + } + + FutureOr unselect() async { + if (state.isDisabled || state.isFreezed) { + return; + } + + emit( + state.copyWith(selected: false), + ); + } } diff --git a/packages/wyatt_ui_kit/lib/src/components/buttons/file_selection_button/file_selection_button.dart b/packages/wyatt_ui_kit/lib/src/components/buttons/file_selection_button/file_selection_button.dart new file mode 100644 index 00000000..44759cc7 --- /dev/null +++ b/packages/wyatt_ui_kit/lib/src/components/buttons/file_selection_button/file_selection_button.dart @@ -0,0 +1,96 @@ +// 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 . + +import 'package:flutter/material.dart' hide ButtonStyle; +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/buttons/cubit/invalid_button_cubit.dart'; +import 'package:wyatt_ui_kit/src/components/buttons/file_selection_button/file_selection_button_screen.dart'; +import 'package:wyatt_ui_kit/src/core/mixin/export_bloc_mixin.dart'; + +part 'file_selection_button.g.dart'; + +@ComponentCopyWithExtension() +class FileSelectionButton extends FileSelectionButtonComponent + with $FileSelectionButtonCWMixin, ExportBloc { + FileSelectionButton({ + super.leading, + super.title, + super.subTitle, + super.disabledStyle, + super.normalStyle, + super.hoveredStyle, + super.focusedStyle, + super.tappedStyle, + super.selectedStyle, + super.invalidStyle, + super.onPressed, + super.mainAxisSize, + super.key, + }); + + final InvalidButtonCubit _cubit = InvalidButtonCubit(); + + @override + InvalidButtonCubit get bloc => _cubit; + + @override + FileSelectionButtonStyle? get disabledStyle => + super.disabledStyle as FileSelectionButtonStyle?; + + @override + FileSelectionButtonStyle? get normalStyle => + super.normalStyle as FileSelectionButtonStyle?; + + @override + FileSelectionButtonStyle? get hoveredStyle => + super.hoveredStyle as FileSelectionButtonStyle?; + + @override + FileSelectionButtonStyle? get focusedStyle => + super.focusedStyle as FileSelectionButtonStyle?; + + @override + FileSelectionButtonStyle? get tappedStyle => + super.tappedStyle as FileSelectionButtonStyle?; + + @override + FileSelectionButtonStyle? get selectedStyle => + super.selectedStyle as FileSelectionButtonStyle?; + + @override + FileSelectionButtonStyle? get invalidStyle => + super.invalidStyle as FileSelectionButtonStyle?; + + @override + Widget build(BuildContext context) => exportBloc( + child: FileSelectionButtonScreen( + leading: leading, + title: title, + subTitle: subTitle, + disabledStyle: disabledStyle, + normalStyle: normalStyle, + hoveredStyle: hoveredStyle, + focusedStyle: focusedStyle, + tappedStyle: tappedStyle, + selectedStyle: selectedStyle, + invalidStyle: invalidStyle, + onPressed: onPressed, + mainAxisSize: mainAxisSize, + key: key, + ), + ); +} diff --git a/packages/wyatt_ui_kit/lib/src/components/buttons/file_selection_button/file_selection_button.g.dart b/packages/wyatt_ui_kit/lib/src/components/buttons/file_selection_button/file_selection_button.g.dart new file mode 100644 index 00000000..d70db729 --- /dev/null +++ b/packages/wyatt_ui_kit/lib/src/components/buttons/file_selection_button/file_selection_button.g.dart @@ -0,0 +1,85 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'file_selection_button.dart'; + +// ************************************************************************** +// ComponentCopyWithGenerator +// ************************************************************************** + +class $FileSelectionButtonCWProxyImpl + implements $FileSelectionButtonComponentCWProxy { + const $FileSelectionButtonCWProxyImpl(this._value); + final FileSelectionButton _value; + @override + FileSelectionButton mainAxisSize(MainAxisSize? mainAxisSize) => + this(mainAxisSize: mainAxisSize); + @override + FileSelectionButton leading(Widget? leading) => this(leading: leading); + @override + FileSelectionButton title(TextWrapper? title) => this(title: title); + @override + FileSelectionButton subTitle(TextWrapper? subTitle) => + this(subTitle: subTitle); + @override + FileSelectionButton disabledStyle(ButtonStyle? disabledStyle) => + this(disabledStyle: disabledStyle); + @override + FileSelectionButton normalStyle(ButtonStyle? normalStyle) => + this(normalStyle: normalStyle); + @override + FileSelectionButton hoveredStyle(ButtonStyle? hoveredStyle) => + this(hoveredStyle: hoveredStyle); + @override + FileSelectionButton focusedStyle(ButtonStyle? focusedStyle) => + this(focusedStyle: focusedStyle); + @override + FileSelectionButton tappedStyle(ButtonStyle? tappedStyle) => + this(tappedStyle: tappedStyle); + @override + FileSelectionButton selectedStyle(ButtonStyle? selectedStyle) => + this(selectedStyle: selectedStyle); + @override + FileSelectionButton invalidStyle(ButtonStyle? invalidStyle) => + this(invalidStyle: invalidStyle); + @override + FileSelectionButton onPressed(void Function(ControlState)? onPressed) => + this(onPressed: onPressed); + @override + FileSelectionButton key(Key? key) => this(key: key); + @override + FileSelectionButton call({ + MainAxisSize? mainAxisSize, + Widget? leading, + TextWrapper? title, + TextWrapper? subTitle, + ButtonStyle? disabledStyle, + ButtonStyle? normalStyle, + ButtonStyle? hoveredStyle, + ButtonStyle? focusedStyle, + ButtonStyle? tappedStyle, + ButtonStyle? selectedStyle, + ButtonStyle? invalidStyle, + void Function(ControlState)? onPressed, + Key? key, + }) => + FileSelectionButton( + leading: leading ?? _value.leading, + title: title ?? _value.title, + subTitle: subTitle ?? _value.subTitle, + disabledStyle: disabledStyle ?? _value.disabledStyle, + normalStyle: normalStyle ?? _value.normalStyle, + hoveredStyle: hoveredStyle ?? _value.hoveredStyle, + focusedStyle: focusedStyle ?? _value.focusedStyle, + tappedStyle: tappedStyle ?? _value.tappedStyle, + selectedStyle: selectedStyle ?? _value.selectedStyle, + invalidStyle: invalidStyle ?? _value.invalidStyle, + onPressed: onPressed ?? _value.onPressed, + mainAxisSize: mainAxisSize ?? _value.mainAxisSize, + key: key ?? _value.key, + ); +} + +mixin $FileSelectionButtonCWMixin on Component { + $FileSelectionButtonComponentCWProxy get copyWith => + $FileSelectionButtonCWProxyImpl(this as FileSelectionButton); +} diff --git a/packages/wyatt_ui_kit/lib/src/components/buttons/file_selection_button/file_selection_button_screen.dart b/packages/wyatt_ui_kit/lib/src/components/buttons/file_selection_button/file_selection_button_screen.dart new file mode 100644 index 00000000..fd92b971 --- /dev/null +++ b/packages/wyatt_ui_kit/lib/src/components/buttons/file_selection_button/file_selection_button_screen.dart @@ -0,0 +1,251 @@ +// 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 . + +import 'package:dotted_border/dotted_border.dart'; +import 'package:flutter/material.dart' hide ButtonStyle; +import 'package:flutter/services.dart'; +import 'package:gap/gap.dart'; +import 'package:wyatt_bloc_helper/wyatt_bloc_helper.dart'; +import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart'; +import 'package:wyatt_ui_kit/src/components/buttons/cubit/button_cubit.dart'; +import 'package:wyatt_ui_kit/src/components/buttons/cubit/invalid_button_cubit.dart'; +import 'package:wyatt_ui_kit/src/components/gradients/gradient_text.dart'; +import 'package:wyatt_ui_kit/src/core/extensions/theme_extensions.dart'; +import 'package:wyatt_ui_kit/src/core/helpers/linear_gradient_helper.dart'; + +class FileSelectionButtonScreen + extends CubitScreen { + const FileSelectionButtonScreen({ + this.leading, + this.title, + this.subTitle, + this.disabledStyle, + this.normalStyle, + this.hoveredStyle, + this.focusedStyle, + this.tappedStyle, + this.selectedStyle, + this.invalidStyle, + this.onPressed, + this.mainAxisSize, + super.key, + }); + + final Widget? leading; + final TextWrapper? title; + final TextWrapper? subTitle; + + final FileSelectionButtonStyle? disabledStyle; + final FileSelectionButtonStyle? normalStyle; + final FileSelectionButtonStyle? hoveredStyle; + final FileSelectionButtonStyle? focusedStyle; + final FileSelectionButtonStyle? tappedStyle; + final FileSelectionButtonStyle? selectedStyle; + final FileSelectionButtonStyle? invalidStyle; + + final void Function(ControlState state)? onPressed; + + final MainAxisSize? mainAxisSize; + + @override + InvalidButtonCubit create(BuildContext context) => InvalidButtonCubit(); + + @override + Widget onBuild(BuildContext context, ButtonState state) { + // Set a default style + FileSelectionButtonStyle? style = + normalStyle ?? const FileSelectionButtonStyle(); + + switch (state.state) { + case ControlState.disabled: + style = disabledStyle ?? style; + break; + case ControlState.hovered: + style = hoveredStyle ?? style; + break; + case ControlState.tapped: + style = tappedStyle ?? style; + break; + case ControlState.focused: + style = focusedStyle ?? style; + break; + case ControlState.normal: + // already done + break; + } + + if (state.isSelected) { + style = selectedStyle ?? style; + } + + if (state.isInvalid) { + style = invalidStyle ?? style; + } + + print(state); + + return Focus( + onFocusChange: (hasFocus) => + hasFocus ? bloc(context).onFocus() : bloc(context).onUnfocus(), + onKeyEvent: (focusNode, event) { + if (event.logicalKey == LogicalKeyboardKey.enter && state.isFocused) { + onPressed?.call(state.state); + bloc(context).onClickUpOut(); + return KeyEventResult.handled; + } + return KeyEventResult.ignored; + }, + child: MouseRegion( + cursor: SystemMouseCursors.click, + onEnter: (event) { + bloc(context).onMouseEnter(); + }, + onExit: (event) { + bloc(context).onMouseLeave(); + }, + child: GestureDetector( + onTapDown: (details) { + bloc(context).onClickDown(); + }, + onTapUp: (details) { + onPressed?.call(state.state); + bloc(context).onClickUpIn(); + }, + onTapCancel: () { + onPressed?.call(state.state); + bloc(context).onClickUpOut(); + }, + child: DottedBorder( + padding: EdgeInsets.zero, + dashPattern: const [5, 5], + strokeWidth: style.stroke ?? 3, + color: style.borderColors?.color ?? context.colorScheme.primary, + borderType: BorderType.RRect, + radius: Radius.circular(style.radius ?? 0), + strokeCap: StrokeCap.square, + child: DecoratedBox( + decoration: BoxDecoration( + color: style.backgroundColors?.color ?? + context.colorScheme.primary, + // if no gradient colors => no default value + gradient: (style.backgroundColors?.isGradient ?? false) + ? LinearGradient( + colors: style.backgroundColors!.colors, + ) + : null, + boxShadow: [ + if (style.shadow != null) ...[style.shadow!] + ], + borderRadius: BorderRadius.all( + Radius.circular(style.radius ?? 0), + ), + ), + child: ConstrainedBox( + constraints: const BoxConstraints( + minWidth: 200, + minHeight: 50, + ), // min sizes for Material buttons + child: Padding( + padding: EdgeInsets.all(style.padding ?? 0), + child: Row( + mainAxisSize: mainAxisSize ?? MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + if (leading != null) ...[ + leading ?? const SizedBox.shrink(), + Gap(style.padding ?? 10), + ], + + // Choose color + // label.style.color ?? + // buttonStyle.foregroundColor.color ?? + // context.textTheme.titleLarge.color + // + // Choose gradient + // label.gradient ?? + // buttonStyle.foregroundColor.colors ?? + // null + Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (title != null) ...[ + Builder( + builder: (context) { + final color = title?.style?.color ?? + style?.foregroundColors?.color ?? + context.textTheme.titleLarge?.color; + final buttonStyleGradient = + (style?.foregroundColors?.isGradient ?? + false) + ? style?.foregroundColors?.colors + : null; + final gradient = + title?.gradient ?? buttonStyleGradient; + + return Text( + title!.text, + style: (title!.style ?? + context.textTheme.titleLarge) + ?.copyWith(color: color), + ).toGradient( + LinearGradientHelper.fromNullableColors( + gradient, + ), + ); + }, + ), + ], + if (subTitle != null) ...[ + Builder( + builder: (context) { + final color = subTitle?.style?.color ?? + style?.foregroundColors?.color ?? + context.textTheme.bodyMedium?.color; + final buttonStyleGradient = + (style?.foregroundColors?.isGradient ?? + false) + ? style?.foregroundColors?.colors + : null; + final gradient = + subTitle?.gradient ?? buttonStyleGradient; + + return Text( + subTitle!.text, + style: (subTitle!.style ?? + context.textTheme.bodyMedium) + ?.copyWith(color: color), + ).toGradient( + LinearGradientHelper.fromNullableColors( + gradient, + ), + ); + }, + ), + ], + ], + ), + ], + ), + ), + ), + ), + ), + ), + ), + ); + } +} diff --git a/packages/wyatt_ui_kit/lib/src/components/buttons/flat_button/flat_button_screen.dart b/packages/wyatt_ui_kit/lib/src/components/buttons/flat_button/flat_button_screen.dart index 1d44a8f0..050ab61e 100644 --- a/packages/wyatt_ui_kit/lib/src/components/buttons/flat_button/flat_button_screen.dart +++ b/packages/wyatt_ui_kit/lib/src/components/buttons/flat_button/flat_button_screen.dart @@ -111,117 +111,114 @@ class FlatButtonScreen extends CubitScreen { onPressed?.call(state.state); bloc(context).onClickUpOut(); }, - child: Material( - color: const Color(0x00000000), - child: Ink( - decoration: BoxDecoration( - color: style.backgroundColors?.color ?? - context.colorScheme.primary, - // If no border color => no default value - border: (style.borderColors != null) - ? (style.borderColors?.isGradient ?? false) - ? GradientBoxBorder( - gradient: LinearGradient( - colors: style.borderColors!.colors, - ), - width: style.stroke ?? 2, - ) - : Border.all( - color: style.borderColors!.color, - width: style.stroke ?? 2, - ) - : null, - // if no gradient colors => no default value - gradient: (style.backgroundColors?.isGradient ?? false) - ? LinearGradient( - colors: style.backgroundColors!.colors, - ) - : null, - boxShadow: [ - if (style.shadow != null) ...[style.shadow!] - ], - borderRadius: BorderRadius.all( - Radius.circular(style.radius ?? 0), - ), + child: DecoratedBox( + decoration: BoxDecoration( + color: style.backgroundColors?.color ?? + context.colorScheme.primary, + // If no border color => no default value + border: (style.borderColors != null) + ? (style.borderColors?.isGradient ?? false) + ? GradientBoxBorder( + gradient: LinearGradient( + colors: style.borderColors!.colors, + ), + width: style.stroke ?? 2, + ) + : Border.all( + color: style.borderColors!.color, + width: style.stroke ?? 2, + ) + : null, + // if no gradient colors => no default value + gradient: (style.backgroundColors?.isGradient ?? false) + ? LinearGradient( + colors: style.backgroundColors!.colors, + ) + : null, + boxShadow: [ + if (style.shadow != null) ...[style.shadow!] + ], + borderRadius: BorderRadius.all( + Radius.circular(style.radius ?? 0), ), - child: ConstrainedBox( - constraints: const BoxConstraints( - minWidth: 88, - minHeight: 36, - ), // min sizes for Material buttons - child: Padding( - padding: EdgeInsets.all(style.padding ?? 0), - child: Row( - mainAxisSize: mainAxisSize ?? MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ + ), + child: ConstrainedBox( + constraints: const BoxConstraints( + minWidth: 88, + minHeight: 36, + ), // min sizes for Material buttons + child: Padding( + padding: EdgeInsets.all(style.padding ?? 0), + child: Row( + mainAxisSize: mainAxisSize ?? MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Builder( + builder: (context) { + final color = style?.foregroundColors?.color; + if (color != null) { + return ColorFiltered( + colorFilter: + ColorFilter.mode(color, BlendMode.srcIn), + child: prefix ?? const SizedBox.shrink(), + ); + } else { + return prefix ?? const SizedBox.shrink(); + } + }, + ), + Gap(style.padding ?? 10), + // Choose color + // label.style.color ?? + // buttonStyle.foregroundColor.color ?? + // context.textTheme.titleLarge.color + // + // Choose gradient + // label.gradient ?? + // buttonStyle.foregroundColor.colors ?? + // null + if (label != null) ...[ Builder( builder: (context) { - final color = style?.foregroundColors?.color; - if (color != null) { - return ColorFiltered( - colorFilter: - ColorFilter.mode(color, BlendMode.srcIn), - child: prefix ?? const SizedBox.shrink(), - ); - } else { - return prefix ?? const SizedBox.shrink(); - } - }, - ), - Gap(style.padding ?? 10), - // Choose color - // label.style.color ?? - // buttonStyle.foregroundColor.color ?? - // context.textTheme.titleLarge.color - // - // Choose gradient - // label.gradient ?? - // buttonStyle.foregroundColor.colors ?? - // null - if (label != null) ...[ - Builder( - builder: (context) { - final color = label?.style?.color ?? - style?.foregroundColors?.color ?? - context.textTheme.titleLarge?.color; - final buttonStyleGradient = - (style?.foregroundColors?.isGradient ?? false) - ? style?.foregroundColors?.colors - : null; - final gradient = - label?.gradient ?? buttonStyleGradient; + final color = label?.style?.color ?? + style?.foregroundColors?.color ?? + context.textTheme.titleLarge?.color; + final buttonStyleGradient = + (style?.foregroundColors?.isGradient ?? false) + ? style?.foregroundColors?.colors + : null; + final gradient = + label?.gradient ?? buttonStyleGradient; - return Text( - label!.text, - style: - (label!.style ?? context.textTheme.titleLarge) - ?.copyWith(color: color), - ).toGradient( - LinearGradientHelper.fromNullableColors( - gradient, - ), - ); - }, - ), - ], - Gap(style.padding ?? 10), - Builder( - builder: (context) { - final color = style?.foregroundColors?.color; - if (color != null) { - return ColorFiltered( - colorFilter: - ColorFilter.mode(color, BlendMode.srcIn), - child: suffix ?? const SizedBox.shrink(), - ); - } else { - return suffix ?? const SizedBox.shrink(); - } + return Text( + label!.text, + style: + (label!.style ?? context.textTheme.titleLarge) + ?.copyWith(color: color), + ).toGradient( + LinearGradientHelper.fromNullableColors( + gradient, + ), + ); }, ), ], - ), + Gap(style.padding ?? 10), + Builder( + builder: (context) { + final color = style?.foregroundColors?.color; + if (color != null) { + return ColorFiltered( + colorFilter: + ColorFilter.mode(color, BlendMode.srcIn), + child: suffix ?? const SizedBox.shrink(), + ); + } else { + return suffix ?? const SizedBox.shrink(); + } + }, + ), + ], ), ), ), diff --git a/packages/wyatt_ui_kit/pubspec.yaml b/packages/wyatt_ui_kit/pubspec.yaml index f600885d..319289e2 100644 --- a/packages/wyatt_ui_kit/pubspec.yaml +++ b/packages/wyatt_ui_kit/pubspec.yaml @@ -9,6 +9,7 @@ environment: sdk: ">=2.19.0 <3.0.0" dependencies: + dotted_border: ^2.0.0+3 equatable: ^2.0.5 flutter: { sdk: flutter } flutter_animate: ^3.0.0