Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: [MDS-669] Fix InputGroup bugs #250

Merged
merged 6 commits into from
Sep 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 0 additions & 22 deletions example/lib/src/storybook/common/widgets/error.dart

This file was deleted.

3 changes: 0 additions & 3 deletions example/lib/src/storybook/stories/text_area.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import 'package:example/src/storybook/common/color_options.dart';
import 'package:example/src/storybook/common/widgets/error.dart';
import 'package:flutter/material.dart';
import 'package:moon_design/moon_design.dart';
import 'package:storybook_flutter/storybook_flutter.dart';
Expand Down Expand Up @@ -124,8 +123,6 @@ class TextAreaStory extends Story {
? "The text should be longer than 10 characters."
: null,
helper: showHelperKnob ? const Text("Supporting text") : null,
errorBuilder: (BuildContext context, String? errorText) =>
StoryErrorWidget(errorText: errorText!),
),
const SizedBox(height: 32),
MoonFilledButton(
Expand Down
7 changes: 0 additions & 7 deletions example/lib/src/storybook/stories/text_input.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import 'package:example/src/storybook/common/color_options.dart';
import 'package:example/src/storybook/common/widgets/error.dart';
import 'package:flutter/material.dart';
import 'package:moon_design/moon_design.dart';
import 'package:storybook_flutter/storybook_flutter.dart';
Expand Down Expand Up @@ -188,8 +187,6 @@ class TextInputStory extends Story {
)
: null,
helper: showHelperKnob ? const Text("Supporting text") : null,
errorBuilder: (BuildContext context, String? errorText) =>
StoryErrorWidget(errorText: errorText!),
),
const SizedBox(height: 16),
StatefulBuilder(
Expand Down Expand Up @@ -236,8 +233,6 @@ class TextInputStory extends Story {
)
: null,
helper: showHelperKnob ? const Text("Supporting text") : null,
errorBuilder: (BuildContext context, String? errorText) =>
StoryErrorWidget(errorText: errorText!),
);
},
),
Expand Down Expand Up @@ -288,8 +283,6 @@ class TextInputStory extends Story {
)
: null,
helper: showHelperKnob ? const Text("Supporting text") : null,
errorBuilder: (BuildContext context, String? errorText) =>
StoryErrorWidget(errorText: errorText!),
),
const SizedBox(height: 32),
MoonFilledButton(
Expand Down
70 changes: 39 additions & 31 deletions example/lib/src/storybook/stories/text_input_group.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import 'package:example/src/storybook/common/color_options.dart';
import 'package:example/src/storybook/common/widgets/error.dart';
import 'package:flutter/material.dart';
import 'package:moon_design/moon_design.dart';
import 'package:storybook_flutter/storybook_flutter.dart';
Expand Down Expand Up @@ -47,27 +46,38 @@ class TextInputGroupStory extends Story {

final backgroundColor = colorTable(context)[backgroundColorKnob ?? 40];

final activeBorderColorKnob = context.knobs.nullable.options(
final borderColorKnob = context.knobs.nullable.options(
label: "borderColor",
description: "MoonColors variants for MoonTextInputGroup border.",
enabled: false,
initial: 0,
// piccolo
options: colorOptions,
);

final borderColor = colorTable(context)[borderColorKnob ?? 40];

final activeChildrenBorderColorKnob = context.knobs.nullable.options(
label: "activeBorderColor",
description: "MoonColors variants for MoonTextInputGroup active border.",
description: "MoonColors variants for MoonTextInputGroup children active border.",
enabled: false,
initial: 0,
// piccolo
options: colorOptions,
);

final activeBorderColor = colorTable(context)[activeBorderColorKnob ?? 40];
final activeBorderColor = colorTable(context)[activeChildrenBorderColorKnob ?? 40];

final inactiveBorderColorKnob = context.knobs.nullable.options(
label: "inactiveBorderColor",
description: "MoonColors variants for MoonTextInputGroup inactive border.",
final errorBorderColorKnob = context.knobs.nullable.options(
label: "errorBorderColor",
description: "MoonColors variants for MoonTextInputGroup error border.",
enabled: false,
initial: 0,
// piccolo
options: colorOptions,
);

final inactiveBorderColor = colorTable(context)[inactiveBorderColorKnob ?? 40];
final errorBorderColor = colorTable(context)[errorBorderColorKnob ?? 40];

final errorColorKnob = context.knobs.nullable.options(
label: "errorColor",
Expand All @@ -80,6 +90,23 @@ class TextInputGroupStory extends Story {

final errorColor = colorTable(context)[errorColorKnob ?? 40];

final orientationKnob = context.knobs.nullable.options(
label: "orientation",
description: "MoonTextInputGroup orientation.",
enabled: false,
initial: MoonTextInputGroupOrientation.vertical,
options: [
const Option(
label: "vertical",
value: MoonTextInputGroupOrientation.vertical,
),
const Option(
label: "horizontal",
value: MoonTextInputGroupOrientation.horizontal,
),
],
);

final borderRadiusKnob = context.knobs.nullable.sliderInt(
label: "borderRadius",
description: "Border radius for MoonTextInputGroup.",
Expand Down Expand Up @@ -113,14 +140,12 @@ class TextInputGroupStory extends Story {
children: [
MoonTextInputGroup(
enabled: enabledKnob,
textColor: textColor,
backgroundColor: backgroundColor,
inactiveBorderColor: inactiveBorderColor,
borderColor: borderColor,
errorColor: errorColor,
borderRadius: borderRadius,
orientation: orientationKnob ?? MoonTextInputGroupOrientation.vertical,
helper: showHelperKnob ? const Text("Supporting text") : null,
errorBuilder: (BuildContext context, List<String> errorMessages) =>
_StoryErrorMessageWidget(errors: errorMessages),
children: [
MoonFormTextInput(
textInputSize: MoonTextInputSize.xl,
Expand All @@ -130,6 +155,7 @@ class TextInputGroupStory extends Story {
textColor: textColor,
hintTextColor: hintTextColor,
activeBorderColor: activeBorderColor,
errorBorderColor: errorBorderColor,
errorColor: errorColor,
borderRadius: borderRadius,
hintText: "Enter text (over 10 characters)",
Expand Down Expand Up @@ -166,7 +192,7 @@ class TextInputGroupStory extends Story {
hintText: "Enter password (123abc)",
validator: (String? value) => value != "123abc" ? "Wrong password." : null,
leading: const MoonIcon(
MoonIcons.search_24,
MoonIcons.password_24,
size: 24,
),
trailing: MouseRegion(
Expand Down Expand Up @@ -204,21 +230,3 @@ class TextInputGroupStory extends Story {
},
);
}

class _StoryErrorMessageWidget extends StatelessWidget {
final List<String> errors;

const _StoryErrorMessageWidget({required this.errors});

@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: List.generate(errors.length * 2 - 1, (int index) {
final int derivedIndex = index ~/ 2;

return index.isEven ? StoryErrorWidget(errorText: errors[derivedIndex]) : const SizedBox(height: 4);
}),
);
}
}
1 change: 1 addition & 0 deletions lib/moon_design.dart
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ export 'package:moon_design/src/widgets/common/base_control.dart';
export 'package:moon_design/src/widgets/common/base_segmented_tab_bar.dart';
export 'package:moon_design/src/widgets/common/effects/focus_effect.dart';
export 'package:moon_design/src/widgets/common/effects/pulse_effect.dart';
export 'package:moon_design/src/widgets/common/error_message_widgets.dart';
export 'package:moon_design/src/widgets/common/icons/icons.dart';
export 'package:moon_design/src/widgets/common/icons/moon_icon.dart';
export 'package:moon_design/src/widgets/common/progress_indicators/circular_progress_indicator.dart';
Expand Down
6 changes: 5 additions & 1 deletion lib/src/theme/text_area/text_area_theme.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,11 @@ class MoonTextAreaTheme extends ThemeExtension<MoonTextAreaTheme> with Diagnosti
borderRadius: tokens.borders.interactiveSm,
transitionDuration: tokens.transitions.defaultTransitionDuration,
transitionCurve: tokens.transitions.defaultTransitionCurve,
helperPadding: EdgeInsets.only(top: tokens.sizes.x4s),
helperPadding: EdgeInsets.only(
left: tokens.sizes.x3s,
top: tokens.sizes.x4s,
right: tokens.sizes.x3s,
),
textPadding: EdgeInsets.all(tokens.sizes.x2s),
textStyle: tokens.typography.body.text16,
helperTextStyle: tokens.typography.body.text12,
Expand Down
6 changes: 5 additions & 1 deletion lib/src/theme/text_input/text_input_theme.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,11 @@ class MoonTextInputTheme extends ThemeExtension<MoonTextInputTheme> with Diagnos
// https://github.com/material-components/material-components-android/blob/master/lib/java/com/google/android/material/textfield/TextInputLayout.java
transitionDuration: const Duration(milliseconds: 167),
transitionCurve: Curves.fastOutSlowIn,
helperPadding: EdgeInsets.only(top: tokens.sizes.x4s),
helperPadding: EdgeInsets.only(
left: tokens.sizes.x3s,
top: tokens.sizes.x4s,
right: tokens.sizes.x3s,
),
helperTextStyle: tokens.typography.body.text12,
),
sizes = sizes ?? MoonTextInputSizes(tokens: tokens);
Expand Down
6 changes: 5 additions & 1 deletion lib/src/theme/text_input_group/text_input_group_theme.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ class MoonTextInputGroupTheme extends ThemeExtension<MoonTextInputGroupTheme> wi
borderRadius: tokens.borders.interactiveSm,
transitionDuration: tokens.transitions.defaultTransitionDuration,
transitionCurve: tokens.transitions.defaultTransitionCurve,
helperPadding: EdgeInsets.only(top: tokens.sizes.x4s),
helperPadding: EdgeInsets.only(
left: tokens.sizes.x3s,
top: tokens.sizes.x4s,
right: tokens.sizes.x3s,
),
textPadding: EdgeInsets.all(tokens.sizes.x2s),
textStyle: tokens.typography.body.text16,
helperTextStyle: tokens.typography.body.text12,
Expand Down
93 changes: 93 additions & 0 deletions lib/src/widgets/common/border_container.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import 'package:flutter/material.dart';
import 'package:moon_design/moon_design.dart';

/// Used to animate the border of a container. Mainly used in [MoonTextInput] and [MoonTextInputGroup]
class BorderContainer extends StatefulWidget {
final Color backgroundColor;
final Decoration? decoration;
final double? height;

final ShapeBorder border;
final Duration duration;
final Curve curve;
final Widget child;

/// Utility widget used to animate the border of a container.
const BorderContainer({
required this.backgroundColor,
this.decoration,
required this.height,
required this.border,
required this.duration,
required this.curve,
required this.child,
});

@override
_BorderContainerState createState() => _BorderContainerState();
}

class _BorderContainerState extends State<BorderContainer> with TickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _borderAnimation;
late ShapeBorderTween _border;

@override
void initState() {
super.initState();

_controller = AnimationController(
duration: widget.duration,
vsync: this,
);
_borderAnimation = CurvedAnimation(
parent: _controller,
curve: widget.curve,
reverseCurve: widget.curve.flipped,
);
_border = ShapeBorderTween(
begin: widget.border,
end: widget.border,
);
}

@override
void dispose() {
_controller.dispose();

super.dispose();
}

@override
void didUpdateWidget(BorderContainer oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.border != oldWidget.border) {
_border = ShapeBorderTween(
begin: oldWidget.border,
end: widget.border,
);
_controller
..value = 0.0
..forward();
}
}

@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _borderAnimation,
builder: (context, child) {
return Container(
height: widget.height,
decoration: widget.decoration ??
ShapeDecorationWithPremultipliedAlpha(
color: widget.backgroundColor,
shape: _border.evaluate(_borderAnimation)!,
),
child: child,
);
},
child: widget.child,
);
}
}
49 changes: 49 additions & 0 deletions lib/src/widgets/common/error_message_widgets.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import 'package:flutter/material.dart';

import 'package:moon_design/src/theme/theme.dart';
import 'package:moon_design/src/widgets/common/icons/icons.dart';
import 'package:moon_design/src/widgets/common/icons/moon_icon.dart';

class MoonErrorMessages extends StatelessWidget {
final List<String> errors;

/// Default error message widget used in [MoonTextInputGroup].
const MoonErrorMessages({required this.errors});

List<String> get _nonEmptyErrors => errors.where((String error) => error.isNotEmpty).toList();

@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: List.generate(_nonEmptyErrors.length * 2 - 1, (int index) {
final int derivedIndex = index ~/ 2;

return index.isEven
? MoonErrorMessage(errorText: _nonEmptyErrors[derivedIndex])
: SizedBox(height: context.moonSizes?.x5s ?? 4);
}),
);
}
}

class MoonErrorMessage extends StatelessWidget {
final String errorText;

/// Default error message widget used in [MoonTextInput] and [MoonTextArea].
const MoonErrorMessage({
super.key,
required this.errorText,
});

@override
Widget build(BuildContext context) {
return Row(
children: [
MoonIcon(MoonIcons.info_16, size: context.moonSizes?.x2s ?? 16),
SizedBox(width: context.moonSizes?.x5s ?? 4),
Text(errorText),
],
);
}
}
Loading