diff --git a/lib/src/theme/alert/alert_colors.dart b/lib/src/theme/alert/alert_colors.dart index a972058c..89cdec3a 100644 --- a/lib/src/theme/alert/alert_colors.dart +++ b/lib/src/theme/alert/alert_colors.dart @@ -2,20 +2,21 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:moon_design/src/theme/colors.dart'; +import 'package:moon_design/src/theme/typography/typography.dart'; import 'package:moon_design/src/utils/color_premul_lerp.dart'; @immutable class MoonAlertColors extends ThemeExtension with DiagnosticableTreeMixin { static final light = MoonAlertColors( backgroundColor: MoonColors.light.gohan, - borderColor: MoonColors.light.bulma, - outlinedVariantColor: MoonColors.light.bulma, + borderColor: MoonTypography.light.colors.bodySecondary, + outlinedVariantColor: MoonTypography.light.colors.bodyPrimary, ); static final dark = MoonAlertColors( backgroundColor: MoonColors.dark.gohan, - borderColor: MoonColors.dark.trunks, - outlinedVariantColor: MoonColors.dark.bulma, + borderColor: MoonTypography.dark.colors.bodySecondary, + outlinedVariantColor: MoonTypography.dark.colors.bodyPrimary, ); /// Alert background color. diff --git a/lib/src/theme/authcode/authcode_colors.dart b/lib/src/theme/authcode/authcode_colors.dart index 5bcb47eb..32e22461 100644 --- a/lib/src/theme/authcode/authcode_colors.dart +++ b/lib/src/theme/authcode/authcode_colors.dart @@ -2,6 +2,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:moon_design/src/theme/colors.dart'; +import 'package:moon_design/src/theme/typography/typography.dart'; import 'package:moon_design/src/utils/color_premul_lerp.dart'; @immutable @@ -15,7 +16,7 @@ class MoonAuthCodeColors extends ThemeExtension with Diagnos activeFillColor: MoonColors.light.gohan, inactiveFillColor: MoonColors.light.gohan, disabledColor: MoonColors.light.beerus, - textColor: MoonColors.light.bulma, + textColor: MoonTypography.light.colors.bodyPrimary, ); static final dark = MoonAuthCodeColors( @@ -27,7 +28,7 @@ class MoonAuthCodeColors extends ThemeExtension with Diagnos activeFillColor: MoonColors.dark.gohan, inactiveFillColor: MoonColors.dark.gohan, disabledColor: MoonColors.dark.beerus, - textColor: MoonColors.dark.bulma, + textColor: MoonTypography.dark.colors.bodyPrimary, ); /// Border color of the selected auth input field. diff --git a/lib/src/theme/segmented_control/segmented_control_colors.dart b/lib/src/theme/segmented_control/segmented_control_colors.dart index 94ff772c..572913e4 100644 --- a/lib/src/theme/segmented_control/segmented_control_colors.dart +++ b/lib/src/theme/segmented_control/segmented_control_colors.dart @@ -11,14 +11,14 @@ class MoonSegmentedControlColors extends ThemeExtension with Diagnostica static final light = MoonSwitchColors( activeTrackColor: MoonColors.light.piccolo, inactiveTrackColor: MoonColors.light.beerus, + activeTextColor: MoonTypography.dark.colors.bodyPrimary, + inactiveTextColor: MoonTypography.light.colors.bodyPrimary, + thumbIconColor: MoonTypography.light.colors.bodyPrimary, thumbColor: MoonColors.light.goten, ); static final dark = MoonSwitchColors( activeTrackColor: MoonColors.dark.piccolo, inactiveTrackColor: MoonColors.dark.beerus, + activeTextColor: MoonTypography.dark.colors.bodyPrimary, + inactiveTextColor: MoonTypography.dark.colors.bodyPrimary, + thumbIconColor: MoonTypography.light.colors.bodyPrimary, thumbColor: MoonColors.dark.goten, ); @@ -24,12 +31,24 @@ class MoonSwitchColors extends ThemeExtension with Diagnostica /// Switch inactive track color. final Color inactiveTrackColor; - /// Switch thumbColor. + /// Switch active track text color. + final Color activeTextColor; + + /// Switch inactive track text color. + final Color inactiveTextColor; + + /// Switch icon Color. + final Color thumbIconColor; + + /// Switch thumb color. final Color thumbColor; const MoonSwitchColors({ required this.activeTrackColor, required this.inactiveTrackColor, + required this.activeTextColor, + required this.inactiveTextColor, + required this.thumbIconColor, required this.thumbColor, }); @@ -37,11 +56,17 @@ class MoonSwitchColors extends ThemeExtension with Diagnostica MoonSwitchColors copyWith({ Color? activeTrackColor, Color? inactiveTrackColor, + Color? activeTextColor, + Color? inactiveTextColor, + Color? thumbIconColor, Color? thumbColor, }) { return MoonSwitchColors( activeTrackColor: activeTrackColor ?? this.activeTrackColor, inactiveTrackColor: inactiveTrackColor ?? this.inactiveTrackColor, + activeTextColor: activeTextColor ?? this.activeTextColor, + inactiveTextColor: inactiveTextColor ?? this.inactiveTextColor, + thumbIconColor: thumbIconColor ?? this.thumbIconColor, thumbColor: thumbColor ?? this.thumbColor, ); } @@ -53,6 +78,9 @@ class MoonSwitchColors extends ThemeExtension with Diagnostica return MoonSwitchColors( activeTrackColor: colorPremulLerp(activeTrackColor, other.activeTrackColor, t)!, inactiveTrackColor: colorPremulLerp(inactiveTrackColor, other.inactiveTrackColor, t)!, + activeTextColor: colorPremulLerp(activeTextColor, other.activeTextColor, t)!, + inactiveTextColor: colorPremulLerp(inactiveTextColor, other.inactiveTextColor, t)!, + thumbIconColor: colorPremulLerp(thumbIconColor, other.thumbIconColor, t)!, thumbColor: colorPremulLerp(thumbColor, other.thumbColor, t)!, ); } @@ -64,6 +92,9 @@ class MoonSwitchColors extends ThemeExtension with Diagnostica ..add(DiagnosticsProperty("type", "MoonSwitchColors")) ..add(ColorProperty("activeTrackColor", activeTrackColor)) ..add(ColorProperty("inactiveTrackColor", inactiveTrackColor)) + ..add(ColorProperty("activeTextColor", activeTextColor)) + ..add(ColorProperty("inactiveTextColor", inactiveTextColor)) + ..add(ColorProperty("thumbIconColor", thumbIconColor)) ..add(ColorProperty("thumbColor", thumbColor)); } } diff --git a/lib/src/theme/toast/toast_colors.dart b/lib/src/theme/toast/toast_colors.dart index 765a0de9..8e4608e2 100644 --- a/lib/src/theme/toast/toast_colors.dart +++ b/lib/src/theme/toast/toast_colors.dart @@ -2,6 +2,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:moon_design/src/theme/colors.dart'; +import 'package:moon_design/src/theme/typography/typography.dart'; import 'package:moon_design/src/utils/color_premul_lerp.dart'; @immutable @@ -9,11 +10,15 @@ class MoonToastColors extends ThemeExtension with Diagnosticabl static final light = MoonToastColors( lightVariantBackgroundColor: MoonColors.light.gohan, darkVariantBackgroundColor: MoonColors.dark.gohan, + lightVariantTextColor: MoonTypography.light.colors.bodyPrimary, + darkVariantTextColor: MoonTypography.dark.colors.bodyPrimary, ); static final dark = MoonToastColors( lightVariantBackgroundColor: MoonColors.dark.gohan, darkVariantBackgroundColor: MoonColors.light.gohan, + lightVariantTextColor: MoonTypography.dark.colors.bodyPrimary, + darkVariantTextColor: MoonTypography.light.colors.bodyPrimary, ); /// Toast light variant background color. @@ -22,19 +27,31 @@ class MoonToastColors extends ThemeExtension with Diagnosticabl /// Toast dark variant background color. final Color darkVariantBackgroundColor; + /// Toast light variant text color. + final Color lightVariantTextColor; + + /// Toast dark variant text color. + final Color darkVariantTextColor; + const MoonToastColors({ required this.lightVariantBackgroundColor, required this.darkVariantBackgroundColor, + required this.lightVariantTextColor, + required this.darkVariantTextColor, }); @override MoonToastColors copyWith({ Color? lightVariantBackgroundColor, Color? darkVariantBackgroundColor, + Color? lightVariantTextColor, + Color? darkVariantTextColor, }) { return MoonToastColors( lightVariantBackgroundColor: lightVariantBackgroundColor ?? this.lightVariantBackgroundColor, darkVariantBackgroundColor: darkVariantBackgroundColor ?? this.darkVariantBackgroundColor, + lightVariantTextColor: lightVariantTextColor ?? this.lightVariantTextColor, + darkVariantTextColor: darkVariantTextColor ?? this.darkVariantTextColor, ); } @@ -45,6 +62,8 @@ class MoonToastColors extends ThemeExtension with Diagnosticabl return MoonToastColors( lightVariantBackgroundColor: colorPremulLerp(lightVariantBackgroundColor, other.lightVariantBackgroundColor, t)!, darkVariantBackgroundColor: colorPremulLerp(darkVariantBackgroundColor, other.darkVariantBackgroundColor, t)!, + lightVariantTextColor: colorPremulLerp(lightVariantTextColor, other.lightVariantTextColor, t)!, + darkVariantTextColor: colorPremulLerp(darkVariantTextColor, other.darkVariantTextColor, t)!, ); } @@ -54,6 +73,8 @@ class MoonToastColors extends ThemeExtension with Diagnosticabl properties ..add(DiagnosticsProperty("type", "MoonToastColors")) ..add(ColorProperty("lightVariantBackgroundColor", lightVariantBackgroundColor)) - ..add(ColorProperty("darkVariantBackgroundColor", darkVariantBackgroundColor)); + ..add(ColorProperty("darkVariantBackgroundColor", darkVariantBackgroundColor)) + ..add(ColorProperty("lightVariantTextColor", lightVariantTextColor)) + ..add(ColorProperty("darkVariantTextColor", darkVariantTextColor)); } } diff --git a/lib/src/widgets/alert/alert.dart b/lib/src/widgets/alert/alert.dart index fff8787c..b5ace162 100644 --- a/lib/src/widgets/alert/alert.dart +++ b/lib/src/widgets/alert/alert.dart @@ -5,6 +5,7 @@ import 'package:moon_design/src/theme/colors.dart'; import 'package:moon_design/src/theme/sizes.dart'; import 'package:moon_design/src/theme/theme.dart'; import 'package:moon_design/src/theme/typography/text_styles.dart'; +import 'package:moon_design/src/theme/typography/typography.dart'; import 'package:moon_design/src/utils/extensions.dart'; import 'package:moon_design/src/utils/shape_decoration_premul.dart'; import 'package:moon_design/src/utils/squircle/squircle_border.dart'; @@ -123,17 +124,6 @@ class _MoonAlertState extends State with SingleTickerProviderStateMix AnimationController? _animationController; Animation? _curvedAnimation; - Color _getElementColor({required Color effectiveBackgroundColor, required Color? elementColor}) { - if (elementColor != null) return elementColor; - - final backgroundLuminance = effectiveBackgroundColor.computeLuminance(); - if (backgroundLuminance > 0.5) { - return MoonColors.light.bulma; - } else { - return MoonColors.dark.bulma; - } - } - TextStyle _getTextStyle({required BuildContext context}) { if (widget.titleTextStyle != null) return widget.titleTextStyle!; @@ -215,13 +205,13 @@ class _MoonAlertState extends State with SingleTickerProviderStateMix widget.borderColor ?? context.moonTheme?.alertTheme.colors.borderColor ?? MoonColors.light.bulma; final Color effectiveLeadingColor = - _getElementColor(effectiveBackgroundColor: effectiveBackgroundColor, elementColor: widget.leadingColor); + widget.leadingColor ?? context.moonTypography?.colors.bodyPrimary ?? MoonTypography.light.colors.bodyPrimary; final Color effectiveTrailingColor = - _getElementColor(effectiveBackgroundColor: effectiveBackgroundColor, elementColor: widget.trailingColor); + widget.trailingColor ?? context.moonTypography?.colors.bodyPrimary ?? MoonTypography.light.colors.bodyPrimary; final Color effectiveTextColor = - _getElementColor(effectiveBackgroundColor: effectiveBackgroundColor, elementColor: widget.textColor); + widget.textColor ?? context.moonTypography?.colors.bodyPrimary ?? MoonTypography.light.colors.bodyPrimary; final EdgeInsetsGeometry effectivePadding = widget.padding ?? context.moonTheme?.alertTheme.properties.padding ?? EdgeInsets.all(MoonSizes.sizes.x2s); diff --git a/lib/src/widgets/authcode/authcode.dart b/lib/src/widgets/authcode/authcode.dart index f36cdce8..e65f95d0 100644 --- a/lib/src/widgets/authcode/authcode.dart +++ b/lib/src/widgets/authcode/authcode.dart @@ -10,6 +10,7 @@ import 'package:moon_design/src/theme/opacity.dart'; import 'package:moon_design/src/theme/sizes.dart'; import 'package:moon_design/src/theme/theme.dart'; import 'package:moon_design/src/theme/typography/text_styles.dart'; +import 'package:moon_design/src/theme/typography/typography.dart'; import 'package:moon_design/src/utils/extensions.dart'; import 'package:moon_design/src/utils/shape_decoration_premul.dart'; import 'package:moon_design/src/utils/squircle/squircle_border.dart'; @@ -309,6 +310,9 @@ class _MoonAuthCodeState extends State with TickerProviderStateMix .merge(widget.errorTextStyle) .copyWith(color: widget.errorTextStyle?.color ?? _effectiveErrorBorderColor); + Color get _resolvedErrorCursorColor => + _isInErrorMode ? _resolvedErrorTextStyle.color ?? _effectiveErrorBorderColor : _effectiveCursorColor; + void _initializeFields() { _initializeFocusNode(); _initializeInputList(); @@ -464,17 +468,6 @@ class _MoonAuthCodeState extends State with TickerProviderStateMix return []; } - Color _getElementColor({required Color effectiveBackgroundColor, required Color? elementColor}) { - if (elementColor != null) return elementColor; - - final backgroundLuminance = effectiveBackgroundColor.computeLuminance(); - if (backgroundLuminance > 0.5) { - return MoonColors.light.bulma; - } else { - return MoonColors.dark.bulma; - } - } - ShapeBorder _getAuthInputFieldShape({required int elementIndex}) { final borderSide = BorderSide( color: _getBorderColorFromIndex(elementIndex), @@ -540,9 +533,7 @@ class _MoonAuthCodeState extends State with TickerProviderStateMix Padding( padding: EdgeInsetsDirectional.only(end: i == widget.authInputFieldCount - 1 ? 0 : _effectiveGap), child: RepaintBoundary( - child: AnimatedContainer( - curve: _animationCurve!, - duration: _animationDuration!, + child: Container( width: _effectiveWidth, height: _effectiveHeight, decoration: ShapeDecorationWithPremultipliedAlpha( @@ -582,7 +573,7 @@ class _MoonAuthCodeState extends State with TickerProviderStateMix child: CustomPaint( size: Size(0, cursorHeight), painter: _CursorPainter( - cursorColor: _effectiveCursorColor, + cursorColor: _resolvedErrorCursorColor, ), ), ), @@ -600,7 +591,7 @@ class _MoonAuthCodeState extends State with TickerProviderStateMix child: CustomPaint( size: Size(0, cursorHeight), painter: _CursorPainter( - cursorColor: _effectiveCursorColor, + cursorColor: _resolvedErrorCursorColor, ), ), ), @@ -731,15 +722,13 @@ class _MoonAuthCodeState extends State with TickerProviderStateMix _effectiveErrorTextStyle = context.moonTheme?.authCodeTheme.properties.errorTextStyle ?? MoonTextStyles.body.text12; - _effectiveTextColor = _getElementColor( - effectiveBackgroundColor: _effectiveActiveFillColor, - elementColor: widget.textColor, - ); + _effectiveTextColor = widget.textColor ?? + context.moonTheme?.authCodeTheme.colors.textColor ?? + MoonTypography.light.colors.bodyPrimary; - _effectiveCursorColor = _getElementColor( - effectiveBackgroundColor: _effectiveSelectedFillColor, - elementColor: widget.authFieldCursorColor, - ); + _effectiveCursorColor = widget.authFieldCursorColor ?? + context.moonTheme?.authCodeTheme.colors.textColor ?? + MoonTypography.light.colors.bodyPrimary; _animationDuration ??= widget.animationDuration ?? context.moonTheme?.authCodeTheme.properties.animationDuration ?? diff --git a/lib/src/widgets/avatar/avatar.dart b/lib/src/widgets/avatar/avatar.dart index c767ae63..0a4b8ddc 100644 --- a/lib/src/widgets/avatar/avatar.dart +++ b/lib/src/widgets/avatar/avatar.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:moon_design/src/theme/avatar/avatar_size_properties.dart'; import 'package:moon_design/src/theme/colors.dart'; import 'package:moon_design/src/theme/theme.dart'; +import 'package:moon_design/src/theme/typography/typography.dart'; import 'package:moon_design/src/utils/extensions.dart'; import 'package:moon_design/src/utils/shape_decoration_premul.dart'; import 'package:moon_design/src/utils/squircle/squircle_border.dart'; @@ -137,19 +138,6 @@ class MoonAvatar extends StatelessWidget { } } - Color _getTextColor(BuildContext context, {required bool isDarkMode, required Color effectiveBackgroundColor}) { - if (backgroundColor == null && context.moonTypography != null) { - return context.moonTypography!.colors.bodyPrimary; - } - - final backgroundLuminance = effectiveBackgroundColor.computeLuminance(); - if (backgroundLuminance > 0.5) { - return MoonColors.light.bulma; - } else { - return MoonColors.dark.bulma; - } - } - @override Widget build(BuildContext context) { final MoonAvatarSizeProperties effectiveMoonAvatarSize = _getMoonAvatarSize(context, avatarSize); @@ -164,8 +152,8 @@ class MoonAvatar extends StatelessWidget { final Color effectiveBadgeColor = badgeColor ?? context.moonTheme?.avatarTheme.colors.badgeColor ?? MoonColors.light.roshi100; - final Color effectiveTextColor = textColor ?? - _getTextColor(context, isDarkMode: context.isDarkMode, effectiveBackgroundColor: effectiveBackgroundColor); + final Color effectiveTextColor = + textColor ?? context.moonTypography?.colors.bodyPrimary ?? MoonTypography.light.colors.bodyPrimary; final double effectiveAvatarHeight = height ?? effectiveMoonAvatarSize.avatarSizeValue; diff --git a/lib/src/widgets/checkbox/checkbox.dart b/lib/src/widgets/checkbox/checkbox.dart index 17ed09fc..8fa86021 100644 --- a/lib/src/widgets/checkbox/checkbox.dart +++ b/lib/src/widgets/checkbox/checkbox.dart @@ -5,6 +5,7 @@ import 'package:moon_design/src/theme/colors.dart'; import 'package:moon_design/src/theme/effects/focus_effects.dart'; import 'package:moon_design/src/theme/opacity.dart'; import 'package:moon_design/src/theme/theme.dart'; +import 'package:moon_design/src/theme/typography/typography.dart'; import 'package:moon_design/src/utils/extensions.dart'; import 'package:moon_design/src/utils/squircle/squircle_border.dart'; import 'package:moon_design/src/utils/touch_target_padding.dart'; @@ -92,7 +93,8 @@ class MoonCheckbox extends StatefulWidget { }) { final bool isInteractive = onChanged != null; - final Color effectiveTextColor = context.moonColors?.bulma ?? MoonColors.light.bulma; + final Color effectiveTextColor = + context.moonTypography?.colors.bodyPrimary ?? MoonTypography.light.colors.bodyPrimary; final TextStyle effectiveTextStyle = context.moonTheme?.typography.body.text14.copyWith(color: effectiveTextColor) ?? diff --git a/lib/src/widgets/common/base_control.dart b/lib/src/widgets/common/base_control.dart index 804923aa..0e17a024 100644 --- a/lib/src/widgets/common/base_control.dart +++ b/lib/src/widgets/common/base_control.dart @@ -266,9 +266,9 @@ class _MoonBaseControlState extends State { void _handleVerticalDragEnd(DragEndDetails dragEndDetails) => _handleTapUp(null); - Color _getFocusColor({required bool isDarkMode, required Color focusColor}) { + Color _getFocusColor({required Color focusColor}) { if (widget.backgroundColor != null) { - return isDarkMode ? widget.backgroundColor!.withOpacity(0.8) : widget.backgroundColor!.withOpacity(0.2); + return context.isDarkMode ? widget.backgroundColor!.withOpacity(0.8) : widget.backgroundColor!.withOpacity(0.2); } else { return focusColor; } @@ -318,7 +318,7 @@ class _MoonBaseControlState extends State { context.moonEffects?.controlFocusEffect.effectColor ?? MoonFocusEffects.lightFocusEffect.effectColor; - final Color focusColor = _getFocusColor(isDarkMode: context.isDarkMode, focusColor: effectiveFocusEffectColor); + final Color focusColor = _getFocusColor(focusColor: effectiveFocusEffectColor); final double effectiveFocusEffectExtent = widget.focusEffectExtent ?? context.moonEffects?.controlFocusEffect.effectExtent ?? diff --git a/lib/src/widgets/segmented_control/segmented_control.dart b/lib/src/widgets/segmented_control/segmented_control.dart index e4ac3090..76875664 100644 --- a/lib/src/widgets/segmented_control/segmented_control.dart +++ b/lib/src/widgets/segmented_control/segmented_control.dart @@ -7,10 +7,10 @@ import 'package:moon_design/src/theme/segmented_control/segmented_control_size_p import 'package:moon_design/src/theme/sizes.dart'; import 'package:moon_design/src/theme/theme.dart'; import 'package:moon_design/src/theme/typography/typography.dart'; +import 'package:moon_design/src/utils/color_tween_premul.dart'; import 'package:moon_design/src/utils/extensions.dart'; import 'package:moon_design/src/utils/shape_decoration_premul.dart'; import 'package:moon_design/src/utils/squircle/squircle_border.dart'; -import 'package:moon_design/src/widgets/common/animated_icon_theme.dart'; import 'package:moon_design/src/widgets/common/base_control.dart'; import 'package:moon_design/src/widgets/common/base_segmented_tab_bar.dart'; import 'package:moon_design/src/widgets/segmented_control/segment.dart'; @@ -196,12 +196,10 @@ class _MoonSegmentedControlState extends State { return AnimatedOpacity( opacity: widget.isDisabled ? effectiveDisabledOpacityValue : 1, duration: effectiveTransitionDuration, - child: AnimatedContainer( + child: Container( height: effectiveHeight, width: widget.width, padding: effectivePadding, - duration: effectiveTransitionDuration, - curve: effectiveTransitionCurve, constraints: BoxConstraints(minWidth: effectiveHeight), decoration: widget.decoration ?? ShapeDecorationWithPremultipliedAlpha( @@ -251,7 +249,7 @@ class _MoonSegmentedControlState extends State { } } -class _SegmentBuilder extends StatelessWidget { +class _SegmentBuilder extends StatefulWidget { final bool isDisabled; final bool isSelected; final Color backgroundColor; @@ -270,12 +268,40 @@ class _SegmentBuilder extends StatelessWidget { required this.segment, }); + @override + State<_SegmentBuilder> createState() => _SegmentBuilderState(); +} + +class _SegmentBuilderState extends State<_SegmentBuilder> with SingleTickerProviderStateMixin { + final ColorTweenWithPremultipliedAlpha _segmentColorTween = ColorTweenWithPremultipliedAlpha(); + final ColorTweenWithPremultipliedAlpha _textColorTween = ColorTweenWithPremultipliedAlpha(); + + Animation? _segmentColor; + Animation? _textColor; + + AnimationController? _animationController; + + void _handleActiveEffect(bool isActive) { + if (isActive) { + _animationController?.forward(); + } else { + _animationController?.reverse(); + } + } + + @override + void dispose() { + _animationController!.dispose(); + + super.dispose(); + } + @override Widget build(BuildContext context) { - final SegmentStyle? segmentStyle = segment.segmentStyle; + final SegmentStyle? segmentStyle = widget.segment.segmentStyle; final BorderRadiusGeometry effectiveSegmentBorderRadius = - segmentStyle?.segmentBorderRadius ?? moonSegmentedControlSizeProperties.segmentBorderRadius; + segmentStyle?.segmentBorderRadius ?? widget.moonSegmentedControlSizeProperties.segmentBorderRadius; final Color effectiveSelectedSegmentColor = segmentStyle?.selectedSegmentColor ?? context.moonTheme?.segmentedControlTheme.colors.selectedSegmentColor ?? @@ -290,76 +316,96 @@ class _SegmentBuilder extends StatelessWidget { context.moonTheme?.segmentedControlTheme.colors.selectedTextColor ?? MoonColors.light.piccolo; - final TextStyle effectiveTextStyle = moonSegmentedControlSizeProperties.textStyle.merge(segmentStyle?.textStyle); + final TextStyle effectiveTextStyle = + widget.moonSegmentedControlSizeProperties.textStyle.merge(segmentStyle?.textStyle); - final double effectiveSegmentGap = segmentStyle?.segmentGap ?? moonSegmentedControlSizeProperties.segmentGap; + final double effectiveSegmentGap = segmentStyle?.segmentGap ?? widget.moonSegmentedControlSizeProperties.segmentGap; final EdgeInsetsGeometry effectiveSegmentPadding = - segmentStyle?.segmentPadding ?? moonSegmentedControlSizeProperties.segmentPadding; + segmentStyle?.segmentPadding ?? widget.moonSegmentedControlSizeProperties.segmentPadding; final EdgeInsets resolvedDirectionalPadding = effectiveSegmentPadding.resolve(Directionality.of(context)); final EdgeInsetsGeometry correctedSegmentPadding = segmentStyle?.segmentPadding == null ? EdgeInsetsDirectional.fromSTEB( - segment.leading == null && segment.label != null ? resolvedDirectionalPadding.left : 0, + widget.segment.leading == null && widget.segment.label != null ? resolvedDirectionalPadding.left : 0, resolvedDirectionalPadding.top, - segment.trailing == null && segment.label != null ? resolvedDirectionalPadding.right : 0, + widget.segment.trailing == null && widget.segment.label != null ? resolvedDirectionalPadding.right : 0, resolvedDirectionalPadding.bottom, ) : resolvedDirectionalPadding; + _animationController ??= AnimationController(duration: widget.transitionDuration, vsync: this); + + _segmentColor ??= + _animationController!.drive(_segmentColorTween.chain(CurveTween(curve: widget.transitionCurve))); + + _textColor ??= _animationController!.drive(_textColorTween.chain(CurveTween(curve: widget.transitionCurve))); + + _segmentColorTween.end = effectiveSelectedSegmentColor; + + _textColorTween + ..begin = effectiveTextColor + ..end = effectiveSelectedTextColor; + return MoonBaseControl( - onLongPress: isDisabled ? null : () => {}, - autofocus: segment.autoFocus, - focusNode: segment.focusNode, - isFocusable: segment.isFocusable, - showFocusEffect: segment.showFocusEffect, + onLongPress: widget.isDisabled ? null : () => {}, + autofocus: widget.segment.autoFocus, + focusNode: widget.segment.focusNode, + isFocusable: widget.segment.isFocusable, + showFocusEffect: widget.segment.showFocusEffect, focusEffectColor: segmentStyle?.focusEffectColor, showScaleAnimation: false, - semanticLabel: segment.semanticLabel, + semanticLabel: widget.segment.semanticLabel, borderRadius: effectiveSegmentBorderRadius.squircleBorderRadius(context), - cursor: isSelected ? SystemMouseCursors.basic : SystemMouseCursors.click, + cursor: widget.isSelected ? SystemMouseCursors.basic : SystemMouseCursors.click, builder: (context, isEnabled, isHovered, isFocused, isPressed) { - final bool isActive = isEnabled && (isSelected || isHovered || isPressed); - - return AnimatedContainer( - duration: transitionDuration, - curve: transitionCurve, - decoration: segmentStyle?.decoration ?? - ShapeDecorationWithPremultipliedAlpha( - color: isActive ? effectiveSelectedSegmentColor : backgroundColor, - shape: MoonSquircleBorder( - borderRadius: effectiveSegmentBorderRadius.squircleBorderRadius(context), - ), - ), - child: AnimatedIconTheme( - size: moonSegmentedControlSizeProperties.iconSizeValue, - duration: transitionDuration, - color: isActive ? effectiveSelectedTextColor : effectiveTextColor, - child: AnimatedDefaultTextStyle( - duration: transitionDuration, - style: effectiveTextStyle.copyWith(color: isActive ? effectiveSelectedTextColor : effectiveTextColor), - child: Center( - child: Padding( - padding: correctedSegmentPadding, - child: Row( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - if (segment.leading != null) - Padding( - padding: EdgeInsets.symmetric(horizontal: effectiveSegmentGap), - child: segment.leading, - ), - if (segment.label != null) segment.label!, - if (segment.trailing != null) - Padding( - padding: EdgeInsets.symmetric(horizontal: effectiveSegmentGap), - child: segment.trailing, - ), - ], + final bool isActive = isEnabled && (widget.isSelected || isHovered || isPressed); + + _handleActiveEffect(isActive); + + return AnimatedBuilder( + animation: _animationController!, + builder: (context, child) { + return DecoratedBox( + decoration: segmentStyle?.decoration ?? + ShapeDecoration( + color: _segmentColor!.value, + shape: MoonSquircleBorder( + borderRadius: effectiveSegmentBorderRadius.squircleBorderRadius(context), + ), ), + child: IconTheme( + data: IconThemeData( + size: widget.moonSegmentedControlSizeProperties.iconSizeValue, + color: _textColor!.value, ), + child: DefaultTextStyle( + style: effectiveTextStyle.copyWith(color: _textColor!.value), + child: child!, + ), + ), + ); + }, + child: Center( + child: Padding( + padding: correctedSegmentPadding, + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + if (widget.segment.leading != null) + Padding( + padding: EdgeInsets.symmetric(horizontal: effectiveSegmentGap), + child: widget.segment.leading, + ), + if (widget.segment.label != null) widget.segment.label!, + if (widget.segment.trailing != null) + Padding( + padding: EdgeInsets.symmetric(horizontal: effectiveSegmentGap), + child: widget.segment.trailing, + ), + ], ), ), ), diff --git a/lib/src/widgets/switch/switch.dart b/lib/src/widgets/switch/switch.dart index 93e5ef2f..9267826d 100644 --- a/lib/src/widgets/switch/switch.dart +++ b/lib/src/widgets/switch/switch.dart @@ -7,6 +7,7 @@ import 'package:moon_design/src/theme/opacity.dart'; import 'package:moon_design/src/theme/shadows.dart'; import 'package:moon_design/src/theme/switch/switch_size_properties.dart'; import 'package:moon_design/src/theme/theme.dart'; +import 'package:moon_design/src/theme/typography/typography.dart'; import 'package:moon_design/src/utils/extensions.dart'; import 'package:moon_design/src/utils/shape_decoration_premul.dart'; import 'package:moon_design/src/utils/squircle/squircle_border.dart'; @@ -150,16 +151,6 @@ class _MoonSwitchState extends State with SingleTickerProviderStateM } } - Color _getTextOrIconColor({required Color backgroundColor}) { - final backgroundLuminance = backgroundColor.computeLuminance(); - - if (backgroundLuminance > 0.5) { - return MoonColors.light.bulma; - } else { - return MoonColors.dark.bulma; - } - } - // `isLinear` must be true if the _curvedAnimationWithOvershoot animation is trying to move the // thumb to the closest end after the most recent drag animation, so the curve // does not change when the controller's value is not 0 or 1. @@ -393,11 +384,13 @@ class _MoonSwitchState extends State with SingleTickerProviderStateM ), ); - final Color iconColor = _getTextOrIconColor(backgroundColor: effectiveThumbColor); + final Color thumbIconColor= context.moonTheme?.switchTheme.colors.thumbIconColor ?? MoonTypography.light.colors.bodyPrimary; - final Color activeTextColor = _getTextOrIconColor(backgroundColor: effectiveActiveTrackColor); + final Color activeTextColor = + context.moonTheme?.switchTheme.colors.activeTextColor ?? MoonTypography.dark.colors.bodyPrimary; - final Color inactiveTextColor = _getTextOrIconColor(backgroundColor: effectiveInactiveTrackColor); + final Color inactiveTextColor = + context.moonTheme?.switchTheme.colors.inactiveTextColor ?? MoonTypography.light.colors.bodyPrimary; return Semantics( label: widget.semanticLabel, @@ -476,7 +469,7 @@ class _MoonSwitchState extends State with SingleTickerProviderStateM Align( alignment: _alignmentAnimation!.value, child: AnimatedIconTheme( - color: iconColor, + color: thumbIconColor, duration: effectiveDuration, size: effectiveThumbSizeValue, child: AnimatedDefaultTextStyle( diff --git a/lib/src/widgets/tab_bar/tab_bar.dart b/lib/src/widgets/tab_bar/tab_bar.dart index d3f986e7..0295d565 100644 --- a/lib/src/widgets/tab_bar/tab_bar.dart +++ b/lib/src/widgets/tab_bar/tab_bar.dart @@ -5,10 +5,9 @@ import 'package:moon_design/src/theme/sizes.dart'; import 'package:moon_design/src/theme/tab_bar/tab_bar_size_properties.dart'; import 'package:moon_design/src/theme/theme.dart'; import 'package:moon_design/src/theme/typography/typography.dart'; +import 'package:moon_design/src/utils/color_tween_premul.dart'; import 'package:moon_design/src/utils/extensions.dart'; -import 'package:moon_design/src/utils/shape_decoration_premul.dart'; import 'package:moon_design/src/utils/squircle/squircle_border.dart'; -import 'package:moon_design/src/widgets/common/animated_icon_theme.dart'; import 'package:moon_design/src/widgets/common/base_control.dart'; import 'package:moon_design/src/widgets/common/base_segmented_tab_bar.dart'; import 'package:moon_design/src/widgets/tab_bar/pill_tab.dart'; @@ -260,13 +259,11 @@ class _MoonTabBarState extends State { final double effectiveGap = widget.gap ?? context.moonTheme?.tabBarTheme.properties.gap ?? MoonSizes.sizes.x5s; - return AnimatedContainer( + return Container( height: effectiveHeight, width: widget.width, padding: widget.padding, decoration: widget.decoration, - duration: _effectiveTransitionDuration, - curve: _effectiveTransitionCurve, constraints: BoxConstraints(minWidth: effectiveHeight), child: BaseSegmentedTabBar( gap: effectiveGap, @@ -289,7 +286,7 @@ class _MoonTabBarState extends State { } } -class _IndicatorTabBuilder extends StatelessWidget { +class _IndicatorTabBuilder extends StatefulWidget { final bool isSelected; final Duration transitionDuration; final Curve transitionCurve; @@ -304,9 +301,39 @@ class _IndicatorTabBuilder extends StatelessWidget { required this.tab, }); + @override + State<_IndicatorTabBuilder> createState() => _IndicatorTabBuilderState(); +} + +class _IndicatorTabBuilderState extends State<_IndicatorTabBuilder> with SingleTickerProviderStateMixin { + final ColorTweenWithPremultipliedAlpha _indicatorColorTween = ColorTweenWithPremultipliedAlpha(); + final ColorTweenWithPremultipliedAlpha _textColorTween = ColorTweenWithPremultipliedAlpha(); + final Tween _indicatorWidthTween = Tween(begin: 0, end: 0); + + Animation? _indicatorColor; + Animation? _textColor; + Animation? _indicatorWidth; + + AnimationController? _animationController; + + void _handleActiveEffect(bool isActive) { + if (isActive) { + _animationController?.forward(); + } else { + _animationController?.reverse(); + } + } + + @override + void dispose() { + _animationController!.dispose(); + + super.dispose(); + } + @override Widget build(BuildContext context) { - final MoonTabStyle? tabStyle = tab.tabStyle; + final MoonTabStyle? tabStyle = widget.tab.tabStyle; final Color effectiveIndicatorColor = tabStyle?.indicatorColor ?? context.moonTheme?.tabBarTheme.colors.indicatorColor ?? MoonColors.light.piccolo; @@ -320,75 +347,98 @@ class _IndicatorTabBuilder extends StatelessWidget { context.moonTheme?.tabBarTheme.colors.selectedTextColor ?? MoonColors.light.piccolo; - final TextStyle effectiveTextStyle = moonTabBarSizeProperties.textStyle.merge(tabStyle?.textStyle); + final TextStyle effectiveTextStyle = widget.moonTabBarSizeProperties.textStyle.merge(tabStyle?.textStyle); - final double effectiveIndicatorHeight = tabStyle?.indicatorHeight ?? moonTabBarSizeProperties.indicatorHeight; + final double effectiveIndicatorHeight = + tabStyle?.indicatorHeight ?? widget.moonTabBarSizeProperties.indicatorHeight; - final double effectiveTabGap = tabStyle?.tabGap ?? moonTabBarSizeProperties.tabGap; + final double effectiveTabGap = tabStyle?.tabGap ?? widget.moonTabBarSizeProperties.tabGap; - final EdgeInsetsGeometry effectiveTabPadding = tabStyle?.tabPadding ?? moonTabBarSizeProperties.tabPadding; + final EdgeInsetsGeometry effectiveTabPadding = tabStyle?.tabPadding ?? widget.moonTabBarSizeProperties.tabPadding; final EdgeInsets resolvedDirectionalPadding = effectiveTabPadding.resolve(Directionality.of(context)); final EdgeInsetsGeometry correctedTabPadding = tabStyle?.tabPadding == null ? EdgeInsetsDirectional.fromSTEB( - tab.leading == null && tab.label != null ? resolvedDirectionalPadding.left : 0, + widget.tab.leading == null && widget.tab.label != null ? resolvedDirectionalPadding.left : 0, resolvedDirectionalPadding.top, - tab.trailing == null && tab.label != null ? resolvedDirectionalPadding.right : 0, + widget.tab.trailing == null && widget.tab.label != null ? resolvedDirectionalPadding.right : 0, resolvedDirectionalPadding.bottom, ) : resolvedDirectionalPadding; + _animationController ??= AnimationController(duration: widget.transitionDuration, vsync: this); + + _indicatorColor ??= + _animationController!.drive(_indicatorColorTween.chain(CurveTween(curve: widget.transitionCurve))); + + _textColor ??= _animationController!.drive(_textColorTween.chain(CurveTween(curve: widget.transitionCurve))); + + _indicatorWidth ??= + _animationController!.drive(_indicatorWidthTween.chain(CurveTween(curve: widget.transitionCurve))); + + _indicatorColorTween.end = effectiveIndicatorColor; + + _textColorTween + ..begin = effectiveTextColor + ..end = effectiveSelectedTextColor; + return MoonBaseControl( - semanticLabel: tab.semanticLabel, - onLongPress: tab.disabled ? null : () => {}, - autofocus: tab.autoFocus, - focusNode: tab.focusNode, - isFocusable: tab.isFocusable, - showFocusEffect: tab.showFocusEffect, + semanticLabel: widget.tab.semanticLabel, + onLongPress: widget.tab.disabled ? null : () => {}, + autofocus: widget.tab.autoFocus, + focusNode: widget.tab.focusNode, + isFocusable: widget.tab.isFocusable, + showFocusEffect: widget.tab.showFocusEffect, focusEffectColor: tabStyle?.focusEffectColor, showScaleAnimation: false, - cursor: isSelected ? SystemMouseCursors.basic : SystemMouseCursors.click, + cursor: widget.isSelected ? SystemMouseCursors.basic : SystemMouseCursors.click, builder: (context, isEnabled, isHovered, isFocused, isPressed) { - final bool isActive = isEnabled && (isSelected || isHovered || isPressed); + final bool isActive = isEnabled && (widget.isSelected || isHovered || isPressed); - return AnimatedContainer( + _handleActiveEffect(isActive); + + return Container( decoration: tabStyle?.decoration, - duration: transitionDuration, - curve: transitionCurve, child: Stack( children: [ - AnimatedIconTheme( - size: moonTabBarSizeProperties.iconSizeValue, - duration: transitionDuration, - color: isActive ? effectiveSelectedTextColor : effectiveTextColor, - child: AnimatedDefaultTextStyle( - duration: transitionDuration, - style: effectiveTextStyle.copyWith(color: isActive ? effectiveSelectedTextColor : effectiveTextColor), - child: Center( - child: Padding( - padding: correctedTabPadding, - child: Row( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - if (tab.leading != null) - Padding( - padding: EdgeInsets.symmetric(horizontal: effectiveTabGap), - child: tab.leading, - ), - if (tab.label != null) - ConstrainedBox( - constraints: BoxConstraints(minHeight: moonTabBarSizeProperties.iconSizeValue), - child: Center(child: tab.label), - ), - if (tab.trailing != null) - Padding( - padding: EdgeInsets.symmetric(horizontal: effectiveTabGap), - child: tab.trailing, - ), - ], - ), + AnimatedBuilder( + animation: _animationController!, + builder: (context, child) { + return IconTheme( + data: IconThemeData( + color: _textColor!.value, + size: widget.moonTabBarSizeProperties.iconSizeValue, + ), + child: DefaultTextStyle( + style: effectiveTextStyle.copyWith(color: _textColor!.value), + child: child!, + ), + ); + }, + child: Center( + child: Padding( + padding: correctedTabPadding, + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + if (widget.tab.leading != null) + Padding( + padding: EdgeInsets.symmetric(horizontal: effectiveTabGap), + child: widget.tab.leading, + ), + if (widget.tab.label != null) + ConstrainedBox( + constraints: BoxConstraints(minHeight: widget.moonTabBarSizeProperties.iconSizeValue), + child: Center(child: widget.tab.label), + ), + if (widget.tab.trailing != null) + Padding( + padding: EdgeInsets.symmetric(horizontal: effectiveTabGap), + child: widget.tab.trailing, + ), + ], ), ), ), @@ -399,15 +449,21 @@ class _IndicatorTabBuilder extends StatelessWidget { right: 0, child: LayoutBuilder( builder: (context, constraints) { + _indicatorWidthTween.end = constraints.maxWidth; + return Align( alignment: Directionality.of(context) == TextDirection.ltr ? Alignment.bottomLeft : Alignment.bottomRight, - child: AnimatedContainer( - duration: transitionDuration, - color: effectiveIndicatorColor, - height: effectiveIndicatorHeight, - width: isActive ? constraints.maxWidth : 0, + child: AnimatedBuilder( + animation: _animationController!, + builder: (context, child) { + return Container( + color: effectiveIndicatorColor, + height: effectiveIndicatorHeight, + width: _indicatorWidth!.value, + ); + }, ), ); }, @@ -421,7 +477,7 @@ class _IndicatorTabBuilder extends StatelessWidget { } } -class _PillTabBuilder extends StatelessWidget { +class _PillTabBuilder extends StatefulWidget { final bool isSelected; final Duration transitionDuration; final Curve transitionCurve; @@ -436,12 +492,40 @@ class _PillTabBuilder extends StatelessWidget { required this.tab, }); + @override + State<_PillTabBuilder> createState() => _PillTabBuilderState(); +} + +class _PillTabBuilderState extends State<_PillTabBuilder> with SingleTickerProviderStateMixin { + final ColorTweenWithPremultipliedAlpha _tabColorTween = ColorTweenWithPremultipliedAlpha(); + final ColorTweenWithPremultipliedAlpha _textColorTween = ColorTweenWithPremultipliedAlpha(); + + Animation? _tabColor; + Animation? _textColor; + + AnimationController? _animationController; + + void _handleActiveEffect(bool isActive) { + if (isActive) { + _animationController?.forward(); + } else { + _animationController?.reverse(); + } + } + + @override + void dispose() { + _animationController!.dispose(); + + super.dispose(); + } + @override Widget build(BuildContext context) { - final MoonPillTabStyle? tabStyle = tab.tabStyle; + final MoonPillTabStyle? tabStyle = widget.tab.tabStyle; final BorderRadiusGeometry effectiveTabBorderRadius = - tabStyle?.borderRadius ?? moonTabBarSizeProperties.borderRadius; + tabStyle?.borderRadius ?? widget.moonTabBarSizeProperties.borderRadius; final Color effectiveSelectedTabColor = tabStyle?.selectedTabColor ?? context.moonTheme?.tabBarTheme.colors.selectedPillTabColor ?? @@ -456,76 +540,94 @@ class _PillTabBuilder extends StatelessWidget { context.moonTheme?.tabBarTheme.colors.selectedPillTextColor ?? MoonTypography.light.colors.bodyPrimary; - final TextStyle effectiveTextStyle = moonTabBarSizeProperties.textStyle.merge(tabStyle?.textStyle); + final TextStyle effectiveTextStyle = widget.moonTabBarSizeProperties.textStyle.merge(tabStyle?.textStyle); - final double effectiveTabGap = tabStyle?.tabGap ?? moonTabBarSizeProperties.tabGap; + final double effectiveTabGap = tabStyle?.tabGap ?? widget.moonTabBarSizeProperties.tabGap; - final EdgeInsetsGeometry effectiveTabPadding = tabStyle?.tabPadding ?? moonTabBarSizeProperties.tabPadding; + final EdgeInsetsGeometry effectiveTabPadding = tabStyle?.tabPadding ?? widget.moonTabBarSizeProperties.tabPadding; final EdgeInsets resolvedDirectionalPadding = effectiveTabPadding.resolve(Directionality.of(context)); final EdgeInsetsGeometry correctedTabPadding = tabStyle?.tabPadding == null ? EdgeInsetsDirectional.fromSTEB( - tab.leading == null && tab.label != null ? resolvedDirectionalPadding.left : 0, + widget.tab.leading == null && widget.tab.label != null ? resolvedDirectionalPadding.left : 0, resolvedDirectionalPadding.top, - tab.trailing == null && tab.label != null ? resolvedDirectionalPadding.right : 0, + widget.tab.trailing == null && widget.tab.label != null ? resolvedDirectionalPadding.right : 0, resolvedDirectionalPadding.bottom, ) : resolvedDirectionalPadding; + _animationController ??= AnimationController(duration: widget.transitionDuration, vsync: this); + + _tabColor ??= _animationController!.drive(_tabColorTween.chain(CurveTween(curve: widget.transitionCurve))); + + _textColor ??= _animationController!.drive(_textColorTween.chain(CurveTween(curve: widget.transitionCurve))); + + _tabColorTween.end = effectiveSelectedTabColor; + + _textColorTween + ..begin = effectiveTextColor + ..end = effectiveSelectedTextColor; + return MoonBaseControl( - semanticLabel: tab.semanticLabel, - onLongPress: tab.disabled ? null : () => {}, - autofocus: tab.autoFocus, - focusNode: tab.focusNode, - isFocusable: tab.isFocusable, - showFocusEffect: tab.showFocusEffect, + semanticLabel: widget.tab.semanticLabel, + onLongPress: widget.tab.disabled ? null : () => {}, + autofocus: widget.tab.autoFocus, + focusNode: widget.tab.focusNode, + isFocusable: widget.tab.isFocusable, + showFocusEffect: widget.tab.showFocusEffect, focusEffectColor: tabStyle?.focusEffectColor, showScaleAnimation: false, borderRadius: effectiveTabBorderRadius.squircleBorderRadius(context), - cursor: isSelected ? SystemMouseCursors.basic : SystemMouseCursors.click, + cursor: widget.isSelected ? SystemMouseCursors.basic : SystemMouseCursors.click, builder: (context, isEnabled, isHovered, isFocused, isPressed) { - final bool isActive = isEnabled && (isSelected || isHovered || isPressed); - - return AnimatedContainer( - duration: transitionDuration, - curve: transitionCurve, - decoration: tabStyle?.decoration ?? - ShapeDecorationWithPremultipliedAlpha( - color: isActive ? effectiveSelectedTabColor : Colors.transparent, - shape: MoonSquircleBorder( - borderRadius: effectiveTabBorderRadius.squircleBorderRadius(context), - ), - ), - child: AnimatedIconTheme( - size: moonTabBarSizeProperties.iconSizeValue, - duration: transitionDuration, - color: isActive ? effectiveSelectedTextColor : effectiveTextColor, - child: AnimatedDefaultTextStyle( - duration: transitionDuration, - style: effectiveTextStyle.copyWith(color: isActive ? effectiveSelectedTextColor : effectiveTextColor), - child: Center( - child: Padding( - padding: correctedTabPadding, - child: Row( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - if (tab.leading != null) - Padding( - padding: EdgeInsets.symmetric(horizontal: effectiveTabGap), - child: tab.leading, - ), - if (tab.label != null) tab.label!, - if (tab.trailing != null) - Padding( - padding: EdgeInsets.symmetric(horizontal: effectiveTabGap), - child: tab.trailing, - ), - ], + final bool isActive = isEnabled && (widget.isSelected || isHovered || isPressed); + + _handleActiveEffect(isActive); + + return AnimatedBuilder( + animation: _animationController!, + builder: (context, child) { + return DecoratedBox( + decoration: tabStyle?.decoration ?? + ShapeDecoration( + color: _tabColor!.value, + shape: MoonSquircleBorder( + borderRadius: effectiveTabBorderRadius.squircleBorderRadius(context), + ), ), + child: IconTheme( + data: IconThemeData( + size: widget.moonTabBarSizeProperties.iconSizeValue, + color: _textColor!.value, + ), + child: DefaultTextStyle( + style: effectiveTextStyle.copyWith(color: _textColor!.value), + child: child!, ), ), + ); + }, + child: Center( + child: Padding( + padding: correctedTabPadding, + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + if (widget.tab.leading != null) + Padding( + padding: EdgeInsets.symmetric(horizontal: effectiveTabGap), + child: widget.tab.leading, + ), + if (widget.tab.label != null) widget.tab.label!, + if (widget.tab.trailing != null) + Padding( + padding: EdgeInsets.symmetric(horizontal: effectiveTabGap), + child: widget.tab.trailing, + ), + ], + ), ), ), ); diff --git a/lib/src/widgets/tag/tag.dart b/lib/src/widgets/tag/tag.dart index b7ffdf70..6d245798 100644 --- a/lib/src/widgets/tag/tag.dart +++ b/lib/src/widgets/tag/tag.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:moon_design/src/theme/colors.dart'; import 'package:moon_design/src/theme/tag/tag_size_properties.dart'; import 'package:moon_design/src/theme/theme.dart'; +import 'package:moon_design/src/theme/typography/typography.dart'; import 'package:moon_design/src/utils/extensions.dart'; import 'package:moon_design/src/utils/shape_decoration_premul.dart'; import 'package:moon_design/src/utils/squircle/squircle_border.dart'; @@ -93,19 +94,6 @@ class MoonTag extends StatelessWidget { } } - Color _getTextColor(BuildContext context, {required bool isDarkMode, required Color effectiveBackgroundColor}) { - if (backgroundColor == null && context.moonTypography != null) { - return context.moonTypography!.colors.bodyPrimary; - } - - final backgroundLuminance = effectiveBackgroundColor.computeLuminance(); - if (backgroundLuminance > 0.5) { - return MoonColors.light.bulma; - } else { - return MoonColors.dark.bulma; - } - } - @override Widget build(BuildContext context) { final MoonTagSizeProperties effectiveMoonTagSize = _getMoonTagSize(context, tagSize); @@ -115,8 +103,8 @@ class MoonTag extends StatelessWidget { final Color effectiveBackgroundColor = backgroundColor ?? context.moonTheme?.tagTheme.colors.backgroundColor ?? MoonColors.light.gohan; - final Color effectiveTextColor = textColor ?? - _getTextColor(context, isDarkMode: context.isDarkMode, effectiveBackgroundColor: effectiveBackgroundColor); + final Color effectiveTextColor = + textColor ?? context.moonTypography?.colors.bodyPrimary ?? MoonTypography.light.colors.bodyPrimary; final double effectiveHeight = height ?? effectiveMoonTagSize.height; @@ -157,7 +145,10 @@ class MoonTag extends StatelessWidget { ), ), child: IconTheme( - data: IconThemeData(color: effectiveTextColor, size: effectiveMoonTagSize.iconSizeValue), + data: IconThemeData( + color: effectiveTextColor, + size: effectiveMoonTagSize.iconSizeValue, + ), child: DefaultTextStyle.merge( style: isUpperCase ? effectiveMoonTagSize.upperCaseTextStyle.copyWith(color: effectiveTextColor) diff --git a/lib/src/widgets/text_area/text_area.dart b/lib/src/widgets/text_area/text_area.dart index cfbe2371..237f48f5 100644 --- a/lib/src/widgets/text_area/text_area.dart +++ b/lib/src/widgets/text_area/text_area.dart @@ -4,11 +4,12 @@ import 'package:flutter/services.dart'; import 'package:moon_design/src/theme/colors.dart'; import 'package:moon_design/src/theme/sizes.dart'; import 'package:moon_design/src/theme/theme.dart'; +import 'package:moon_design/src/theme/typography/typography.dart'; import 'package:moon_design/src/widgets/text_input/form_text_input.dart'; typedef MoonTextAreaErrorBuilder = Widget Function(BuildContext context, String? errorText); -class MoonTextArea extends StatefulWidget { +class MoonTextArea extends StatelessWidget { /// Used to set the auto validation mode. final AutovalidateMode autovalidateMode; @@ -279,130 +280,116 @@ class MoonTextArea extends StatefulWidget { this.helper, }); - @override - State createState() => _MoonTextAreaState(); -} - -class _MoonTextAreaState extends State { - Color _getTextColor(BuildContext context, {required Color effectiveBackgroundColor}) { - final backgroundLuminance = effectiveBackgroundColor.computeLuminance(); - if (backgroundLuminance > 0.5) { - return MoonColors.light.bulma; - } else { - return MoonColors.dark.bulma; - } - } - @override Widget build(BuildContext context) { final BorderRadiusGeometry effectiveBorderRadius = - widget.borderRadius ?? context.moonTheme?.textAreaTheme.properties.borderRadius ?? BorderRadius.circular(8); + borderRadius ?? context.moonTheme?.textAreaTheme.properties.borderRadius ?? BorderRadius.circular(8); final Color effectiveBackgroundColor = - widget.backgroundColor ?? context.moonTheme?.textAreaTheme.colors.backgroundColor ?? MoonColors.light.gohan; + backgroundColor ?? context.moonTheme?.textAreaTheme.colors.backgroundColor ?? MoonColors.light.gohan; - final Color effectiveActiveBorderColor = widget.activeBorderColor ?? + final Color effectiveActiveBorderColor = activeBorderColor ?? context.moonTheme?.textAreaTheme.colors.activeBorderColor ?? MoonColors.light.piccolo; - final Color effectiveInactiveBorderColor = widget.inactiveBorderColor ?? + final Color effectiveInactiveBorderColor = inactiveBorderColor ?? context.moonTheme?.textAreaTheme.colors.inactiveBorderColor ?? MoonColors.light.beerus; - final Color effectiveErrorBorderColor = widget.errorBorderColor ?? + final Color effectiveErrorBorderColor = errorBorderColor ?? context.moonTheme?.textAreaTheme.colors.errorBorderColor ?? MoonColors.light.chiChi100; final Color effectiveHoverBorderColor = - widget.hoverBorderColor ?? context.moonTheme?.textInputTheme.colors.hoverBorderColor ?? MoonColors.light.beerus; + hoverBorderColor ?? context.moonTheme?.textInputTheme.colors.hoverBorderColor ?? MoonColors.light.beerus; final Color effectiveTextColor = - widget.textColor ?? _getTextColor(context, effectiveBackgroundColor: effectiveBackgroundColor); + textColor ?? context.moonTypography?.colors.bodyPrimary ?? MoonTypography.light.colors.bodyPrimary; final Color effectiveHintTextColor = - widget.hintTextColor ?? context.moonTheme?.textAreaTheme.colors.hintTextColor ?? MoonColors.light.trunks; + hintTextColor ?? context.moonTheme?.textAreaTheme.colors.hintTextColor ?? MoonColors.light.trunks; - final EdgeInsetsGeometry effectiveHelperPadding = widget.helperPadding ?? + final EdgeInsetsGeometry effectiveHelperPadding = helperPadding ?? context.moonTheme?.textInputTheme.properties.helperPadding ?? EdgeInsets.symmetric(horizontal: MoonSizes.sizes.x3s, vertical: MoonSizes.sizes.x4s); final EdgeInsetsGeometry effectiveTextPadding = - widget.textPadding ?? context.moonTheme?.textAreaTheme.properties.textPadding ?? const EdgeInsets.all(16); + textPadding ?? context.moonTheme?.textAreaTheme.properties.textPadding ?? const EdgeInsets.all(16); final TextStyle effectiveTextStyle = - widget.textStyle ?? context.moonTheme?.textAreaTheme.properties.textStyle ?? const TextStyle(fontSize: 16); + textStyle ?? context.moonTheme?.textAreaTheme.properties.textStyle ?? const TextStyle(fontSize: 16); - final TextStyle effectiveHelperTextStyle = widget.helperTextStyle ?? + final TextStyle effectiveHelperTextStyle = helperTextStyle ?? context.moonTheme?.textAreaTheme.properties.helperTextStyle ?? const TextStyle(fontSize: 12); - final Duration effectiveTransitionDuration = widget.transitionDuration ?? + final Duration effectiveTransitionDuration = transitionDuration ?? context.moonTheme?.textAreaTheme.properties.transitionDuration ?? const Duration(milliseconds: 200); final Curve effectiveTransitionCurve = - widget.transitionCurve ?? context.moonTheme?.textAreaTheme.properties.transitionCurve ?? Curves.easeInOutCubic; + transitionCurve ?? context.moonTheme?.textAreaTheme.properties.transitionCurve ?? Curves.easeInOutCubic; return MoonFormTextInput( activeBorderColor: effectiveActiveBorderColor, - autocorrect: widget.autocorrect, - autofillHints: widget.autofillHints, - autofocus: widget.autofocus, - autovalidateMode: widget.autovalidateMode, + autocorrect: autocorrect, + autofillHints: autofillHints, + autofocus: autofocus, + autovalidateMode: autovalidateMode, backgroundColor: effectiveBackgroundColor, borderRadius: effectiveBorderRadius, - controller: widget.controller, + controller: controller, cursorColor: effectiveTextColor, - enabled: widget.enabled, - enableIMEPersonalizedLearning: widget.enableIMEPersonalizedLearning, - enableInteractiveSelection: widget.enableInteractiveSelection, - enableSuggestions: widget.enableSuggestions, + enabled: enabled, + enableIMEPersonalizedLearning: enableIMEPersonalizedLearning, + enableInteractiveSelection: enableInteractiveSelection, + enableSuggestions: enableSuggestions, errorBorderColor: effectiveErrorBorderColor, - errorBuilder: widget.errorBuilder, - expands: widget.height != null, - focusNode: widget.focusNode, - showFocusEffect: widget.showFocusEffect, - height: widget.height, - helper: widget.helper, + errorBuilder: errorBuilder, + expands: height != null, + focusNode: focusNode, + showFocusEffect: showFocusEffect, + height: height, + helper: helper, helperPadding: effectiveHelperPadding, helperTextStyle: effectiveHelperTextStyle, - hintText: widget.hintText, + hintText: hintText, hintTextColor: effectiveHintTextColor, hoverBorderColor: effectiveHoverBorderColor, inactiveBorderColor: effectiveInactiveBorderColor, - initialValue: widget.initialValue, - inputFormatters: widget.inputFormatters, - keyboardAppearance: widget.keyboardAppearance, + initialValue: initialValue, + inputFormatters: inputFormatters, + keyboardAppearance: keyboardAppearance, keyboardType: TextInputType.multiline, - maxLength: widget.maxLength, - maxLengthEnforcement: widget.maxLengthEnforcement, + maxLength: maxLength, + maxLengthEnforcement: maxLengthEnforcement, maxLines: null, - minLines: widget.minLines, - onChanged: widget.onChanged, - onEditingComplete: widget.onEditingComplete, - onFieldSubmitted: widget.onSubmitted, - onSaved: widget.onSaved, - onTap: widget.onTap, - onTapOutside: widget.onTapOutside, + minLines: minLines, + onChanged: onChanged, + onEditingComplete: onEditingComplete, + onFieldSubmitted: onSubmitted, + onSaved: onSaved, + onTap: onTap, + onTapOutside: onTapOutside, padding: effectiveTextPadding, - readOnly: widget.readOnly, - restorationId: widget.restorationId, - scrollController: widget.scrollController, - scrollPadding: widget.scrollPadding, - scrollPhysics: widget.scrollPhysics, - decoration: widget.decoration, - showCursor: widget.showCursor, - strutStyle: widget.strutStyle, + readOnly: readOnly, + restorationId: restorationId, + scrollController: scrollController, + scrollPadding: scrollPadding, + scrollPhysics: scrollPhysics, + decoration: decoration, + showCursor: showCursor, + strutStyle: strutStyle, style: effectiveTextStyle.copyWith(color: effectiveTextColor), - textAlign: widget.textAlign, + textAlign: textAlign, textAlignVertical: TextAlignVertical.top, - textCapitalization: widget.textCapitalization, + textCapitalization: textCapitalization, textColor: effectiveTextColor, - textDirection: widget.textDirection, - textInputAction: widget.textInputAction, + textDirection: textDirection, + textInputAction: textInputAction, transitionCurve: effectiveTransitionCurve, transitionDuration: effectiveTransitionDuration, - validator: widget.validator, + validator: validator, ); } } diff --git a/lib/src/widgets/text_input/input_decorator.dart b/lib/src/widgets/text_input/input_decorator.dart index ca297b44..fdd6145a 100644 --- a/lib/src/widgets/text_input/input_decorator.dart +++ b/lib/src/widgets/text_input/input_decorator.dart @@ -197,7 +197,7 @@ class _BorderContainerState extends State<_BorderContainer> with TickerProviderS parent: _hoverColorController, curve: Curves.linear, ); - _hoverColorTween = ColorTweenWithPremultipliedAlpha(end: widget.hoverColor); + _hoverColorTween = ColorTweenWithPremultipliedAlpha(begin: Colors.transparent, end: widget.hoverColor); } @override @@ -220,7 +220,7 @@ class _BorderContainerState extends State<_BorderContainer> with TickerProviderS ..forward(); } if (widget.hoverColor != oldWidget.hoverColor) { - _hoverColorTween = ColorTweenWithPremultipliedAlpha(end: widget.hoverColor); + _hoverColorTween = ColorTweenWithPremultipliedAlpha(begin: Colors.transparent, end: widget.hoverColor); } if (widget.isHovering != oldWidget.isHovering) { if (widget.isHovering) { diff --git a/lib/src/widgets/text_input/text_input.dart b/lib/src/widgets/text_input/text_input.dart index 31c956b2..15ecccbd 100644 --- a/lib/src/widgets/text_input/text_input.dart +++ b/lib/src/widgets/text_input/text_input.dart @@ -15,6 +15,7 @@ import 'package:moon_design/src/theme/opacity.dart'; import 'package:moon_design/src/theme/sizes.dart'; import 'package:moon_design/src/theme/text_input/text_input_size_properties.dart'; import 'package:moon_design/src/theme/theme.dart'; +import 'package:moon_design/src/theme/typography/typography.dart'; import 'package:moon_design/src/utils/extensions.dart'; import 'package:moon_design/src/utils/shape_decoration_premul.dart'; import 'package:moon_design/src/utils/squircle/squircle_border.dart'; @@ -818,9 +819,11 @@ class _MoonTextInputState extends State bool _showSelectionHandles = false; RestorableTextEditingController? _controller; + TextEditingController get _effectiveController => widget.controller ?? _controller!.value; FocusNode? _focusNode; + FocusNode get _effectiveFocusNode => widget.focusNode ?? (_focusNode ??= FocusNode()); EditableTextState? get _editableText => editableTextKey.currentState; @@ -970,15 +973,6 @@ class _MoonTextInputState extends State } } - Color _getTextColor(BuildContext context, {required Color effectiveBackgroundColor}) { - final backgroundLuminance = effectiveBackgroundColor.computeLuminance(); - if (backgroundLuminance > 0.5) { - return MoonColors.light.bulma; - } else { - return MoonColors.dark.bulma; - } - } - // AutofillClient implementation start. @override String get autofillId => _editableText!.autofillId; @@ -1000,6 +994,7 @@ class _MoonTextInputState extends State return _editableText!.textInputConfiguration.copyWith(autofillConfiguration: autofillConfiguration); } + // AutofillClient implementation end. @override @@ -1014,6 +1009,7 @@ class _MoonTextInputState extends State @override bool get selectionEnabled => widget.selectionEnabled; + // End of API for TextSelectionGestureDetectorBuilderDelegate. @override @@ -1138,7 +1134,7 @@ class _MoonTextInputState extends State context.isDarkMode ? effectiveErrorBorderColor.withOpacity(0.4) : effectiveErrorBorderColor.withOpacity(0.2); final Color effectiveTextColor = - widget.textColor ?? _getTextColor(context, effectiveBackgroundColor: effectiveBackgroundColor); + widget.textColor ?? context.moonTypography?.colors.bodyPrimary ?? MoonTypography.light.colors.bodyPrimary; final Color effectiveHintTextColor = widget.hintTextColor ?? context.moonTheme?.textInputTheme.colors.supportingTextColor ?? MoonColors.light.trunks; @@ -1346,7 +1342,8 @@ class _MoonTextInputState extends State magnifierConfiguration: widget.magnifierConfiguration ?? TextMagnifier.adaptiveMagnifierConfiguration, maxLines: widget.maxLines, minLines: widget.minLines, - mouseCursor: MouseCursor.defer, // MoonTextInput will handle the cursor + mouseCursor: MouseCursor.defer, + // MoonTextInput will handle the cursor obscureText: widget.obscureText, obscuringCharacter: widget.obscuringCharacter, onAppPrivateCommand: widget.onAppPrivateCommand, diff --git a/lib/src/widgets/toast/toast.dart b/lib/src/widgets/toast/toast.dart index 0782bd76..c9300cd3 100644 --- a/lib/src/widgets/toast/toast.dart +++ b/lib/src/widgets/toast/toast.dart @@ -7,6 +7,7 @@ import 'package:moon_design/src/theme/colors.dart'; import 'package:moon_design/src/theme/shadows.dart'; import 'package:moon_design/src/theme/sizes.dart'; import 'package:moon_design/src/theme/theme.dart'; +import 'package:moon_design/src/theme/typography/typography.dart'; import 'package:moon_design/src/utils/extensions.dart'; import 'package:moon_design/src/utils/shape_decoration_premul.dart'; import 'package:moon_design/src/utils/squircle/squircle_border.dart'; @@ -94,16 +95,6 @@ class MoonToast { /// The widget in the trailing slot of the toast. Widget? trailing, }) { - Color getElementColor({required Color effectiveBackgroundColor}) { - final backgroundLuminance = effectiveBackgroundColor.computeLuminance(); - - if (backgroundLuminance > 0.5) { - return MoonColors.light.bulma; - } else { - return MoonColors.dark.bulma; - } - } - final BorderRadiusGeometry effectiveBorderRadius = borderRadius ?? context.moonTheme?.toastTheme.properties.borderRadius ?? MoonBorders.borders.surfaceSm; @@ -112,7 +103,9 @@ class MoonToast { ? (context.moonTheme?.toastTheme.colors.lightVariantBackgroundColor ?? MoonColors.light.gohan) : (context.moonTheme?.toastTheme.colors.darkVariantBackgroundColor ?? MoonColors.dark.gohan)); - final Color effectiveElementColor = getElementColor(effectiveBackgroundColor: effectiveBackgroundColor); + final Color effectiveElementColor = variant == MoonToastVariant.original + ? (context.moonTheme?.toastTheme.colors.lightVariantTextColor ?? MoonTypography.light.colors.bodyPrimary) + : (context.moonTheme?.toastTheme.colors.darkVariantTextColor ?? MoonTypography.dark.colors.bodyPrimary); final double effectiveGap = gap ?? context.moonTheme?.toastTheme.properties.gap ?? MoonSizes.sizes.x2s; diff --git a/lib/src/widgets/tooltip/tooltip.dart b/lib/src/widgets/tooltip/tooltip.dart index 7ff394cb..420cdf83 100644 --- a/lib/src/widgets/tooltip/tooltip.dart +++ b/lib/src/widgets/tooltip/tooltip.dart @@ -5,6 +5,7 @@ import 'package:moon_design/src/theme/colors.dart'; import 'package:moon_design/src/theme/shadows.dart'; import 'package:moon_design/src/theme/theme.dart'; import 'package:moon_design/src/theme/typography/text_styles.dart'; +import 'package:moon_design/src/theme/typography/typography.dart'; import 'package:moon_design/src/utils/shape_decoration_premul.dart'; import 'package:moon_design/src/widgets/tooltip/tooltip_shape.dart'; @@ -211,19 +212,6 @@ class _MoonTooltipState extends State with RouteAware, SingleTicker widget.onTap?.call(); } - Color _getTextColor(BuildContext context, {required Color effectiveBackgroundColor}) { - if (widget.backgroundColor == null && context.moonTypography != null) { - return context.moonTypography!.colors.bodyPrimary; - } - - final backgroundLuminance = effectiveBackgroundColor.computeLuminance(); - if (backgroundLuminance > 0.5) { - return MoonColors.light.bulma; - } else { - return MoonColors.dark.bulma; - } - } - _TooltipPositionProperties _resolveTooltipPositionParameters({ required MoonTooltipPosition tooltipPosition, required double arrowTipDistance, @@ -403,7 +391,8 @@ class _MoonTooltipState extends State with RouteAware, SingleTicker final Color effectiveBackgroundColor = widget.backgroundColor ?? context.moonTheme?.tooltipTheme.colors.backgroundColor ?? MoonColors.light.gohan; - final Color effectiveTextColor = _getTextColor(context, effectiveBackgroundColor: effectiveBackgroundColor); + final Color effectiveTextColor = + context.moonTypography?.colors.bodyPrimary ?? MoonTypography.light.colors.bodyPrimary; final double effectiveArrowBaseWidth = widget.arrowBaseWidth ?? context.moonTheme?.tooltipTheme.properties.arrowBaseWidth ?? 16;