Instantly share code, notes, and snippets.
Created
January 23, 2025 12:58
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
-
Save mortezanazari-hub/512457adaaa44aea8e3c2cfc494064ac to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /// {@template app_text_button} | |
| /// یک ویجت دکمه متنی سفارشی که با پلتفرم سازگار است. | |
| /// A custom text button widget that adapts to the platform. | |
| /// {@endtemplate} | |
| abstract class AppTextButton extends StatelessWidget { | |
| /// {@macro app_text_button} | |
| const AppTextButton({ | |
| super.key, | |
| required this.label, | |
| this.onTap, | |
| this.leading, | |
| this.trailing, | |
| this.appButtonSize = AppButtonSize.medium, | |
| }); | |
| /// برچسب دکمه متنی. | |
| /// The label for the text button. | |
| final String label; | |
| /// تابع callback برای دکمه متنی. | |
| /// The callback function for the text button. | |
| final VoidCallback? onTap; | |
| /// آیکون ابتدایی دکمه متنی. | |
| /// The leading icon for the text button. | |
| final IconBuilder? leading; | |
| /// آیکون انتهایی دکمه متنی. | |
| /// The trailing icon for the text button. | |
| final IconBuilder? trailing; | |
| /// اندازه دکمه متنی. | |
| /// The size of the text button. | |
| final AppButtonSize appButtonSize; | |
| /// رنگ پسزمینه دکمه متنی. | |
| /// The background color for the text button. | |
| Color backgroundColor(BuildContext context); | |
| /// رنگ فوکوس دکمه متنی. | |
| /// The focus color for the text button. | |
| Color focusColor(BuildContext context); | |
| /// رنگ هاور دکمه متنی. | |
| /// The hover color for the text button. | |
| Color hoverColor(BuildContext context); | |
| /// رنگ غیرفعال دکمه متنی. | |
| /// The disabled color for the text button. | |
| Color disabledColor(BuildContext context); | |
| /// رنگ متن دکمه متنی. | |
| /// The text color for the text button. | |
| Color textColor(BuildContext context); | |
| /// رنگ متن غیرفعال دکمه متنی. | |
| /// The disabled text color for the text button. | |
| Color disabledTextColor(BuildContext context) { | |
| return context.buttonTheme.primaryTextDisabled; | |
| } | |
| /// حاشیه پیشفرض دکمه متنی. | |
| /// The default border for the text button. | |
| BorderSide defaultBorder(BuildContext context) => BorderSide.none; | |
| /// حاشیه فوکوس دکمه متنی. | |
| /// The focused border for the text button. | |
| BorderSide focusedBorder(BuildContext context) => BorderSide.none; | |
| /// حاشیه هاور دکمه متنی. | |
| /// The hover border for the text button. | |
| BorderSide hoverBorder(BuildContext context) => BorderSide.none; | |
| /// حاشیه غیرفعال دکمه متنی. | |
| /// The disabled border for the text button. | |
| BorderSide disabledBorder(BuildContext context) => BorderSide.none; | |
| } | |
| @override | |
| Widget build(BuildContext context) { | |
| final betweenSpace = switch (appButtonSize) { | |
| AppButtonSize.small || | |
| AppButtonSize.xSmall || | |
| AppButtonSize.medium => | |
| AppSpacing.xs, | |
| AppButtonSize.large || AppButtonSize.xlarge => AppSpacing.sm, | |
| AppButtonSize.xxLarge => AppSpacing.lg, | |
| }; | |
| final inputTextColor = WidgetStateProperty.resolveWith( | |
| (states) { | |
| if (states.contains(WidgetState.disabled)) { | |
| return disabledTextColor(context); | |
| } | |
| return textColor(context); | |
| }, | |
| ); | |
| return ElevatedButton( | |
| style: ButtonStyle( | |
| elevation: WidgetStateProperty.all(0), | |
| splashFactory: NoSplash.splashFactory, | |
| overlayColor: WidgetStateProperty.resolveWith( | |
| (states) { | |
| if (states.contains(WidgetState.disabled)) { | |
| return disabledColor(context); | |
| } | |
| if (states.contains(WidgetState.hovered)) { | |
| return hoverColor(context); | |
| } | |
| if (states.contains(WidgetState.focused)) { | |
| return focusColor(context); | |
| } | |
| if (states.contains(WidgetState.pressed)) { | |
| return focusColor(context); | |
| } | |
| return backgroundColor(context); | |
| }, | |
| ), | |
| shape: WidgetStateProperty.resolveWith( | |
| (states) { | |
| const shape = RoundedRectangleBorder( | |
| borderRadius: BorderRadius.all(AppRadius.md), | |
| ); | |
| if (states.contains(WidgetState.disabled)) { | |
| return shape.copyWith(side: disabledBorder(context)); | |
| } | |
| if (states.contains(WidgetState.focused)) { | |
| return shape.copyWith(side: focusedBorder(context)); | |
| } | |
| if (states.contains(WidgetState.hovered)) { | |
| return shape.copyWith(side: hoverBorder(context)); | |
| } | |
| if (states.contains(WidgetState.pressed)) { | |
| return shape.copyWith(side: focusedBorder(context)); | |
| } | |
| return shape.copyWith(side: defaultBorder(context)); | |
| }, | |
| ), | |
| backgroundColor: WidgetStateProperty.resolveWith( | |
| (states) { | |
| if (states.contains(WidgetState.disabled)) { | |
| return disabledColor(context); | |
| } | |
| if (states.contains(WidgetState.hovered)) { | |
| return hoverColor(context); | |
| } | |
| if (states.contains(WidgetState.focused)) { | |
| return focusColor(context); | |
| } | |
| if (states.contains(WidgetState.pressed)) { | |
| return focusColor(context); | |
| } | |
| return backgroundColor(context); | |
| }, | |
| ), | |
| foregroundColor: inputTextColor, | |
| fixedSize: WidgetStateProperty.all( | |
| switch (appButtonSize) { | |
| AppButtonSize.small || | |
| AppButtonSize.xSmall => | |
| const Size(double.infinity, 36), | |
| AppButtonSize.medium => const Size(double.infinity, 40), | |
| AppButtonSize.large => const Size(double.infinity, 44), | |
| AppButtonSize.xlarge => const Size(double.infinity, 48), | |
| AppButtonSize.xxLarge => const Size(double.infinity, 56), | |
| }, | |
| ), | |
| padding: WidgetStateProperty.all( | |
| switch (appButtonSize) { | |
| AppButtonSize.small || | |
| AppButtonSize.xSmall => | |
| const EdgeInsets.symmetric(horizontal: 12), | |
| AppButtonSize.medium => const EdgeInsets.symmetric(horizontal: 16), | |
| AppButtonSize.large => const EdgeInsets.symmetric(horizontal: 16), | |
| AppButtonSize.xlarge => const EdgeInsets.symmetric(horizontal: 20), | |
| AppButtonSize.xxLarge => const EdgeInsets.symmetric(horizontal: 24), | |
| }, | |
| ), | |
| ), | |
| onPressed: onTap, | |
| child: Row( | |
| mainAxisAlignment: MainAxisAlignment.center, | |
| mainAxisSize: MainAxisSize.min, | |
| children: [ | |
| if (leading != null) ...[ | |
| leading!( | |
| onTap != null ? textColor(context) : disabledTextColor(context), | |
| ), | |
| SizedBox(width: betweenSpace), | |
| ], | |
| Padding( | |
| padding: const EdgeInsets.symmetric(horizontal: AppSpacing.xxs), | |
| child: Text( | |
| label, | |
| style: switch (appButtonSize) { | |
| AppButtonSize.small || | |
| AppButtonSize.xSmall => | |
| context.typography.buttonSmall, | |
| AppButtonSize.medium => context.typography.buttonMedium, | |
| AppButtonSize.large => context.typography.buttonLarge, | |
| AppButtonSize.xlarge => context.typography.buttonXLarge, | |
| AppButtonSize.xxLarge => context.typography.button2XLarge, | |
| }, | |
| ), | |
| ), | |
| if (trailing != null) ...[ | |
| SizedBox(width: betweenSpace), | |
| trailing!( | |
| onTap != null ? textColor(context) : disabledTextColor(context), | |
| ), | |
| ], | |
| ], | |
| ), | |
| ); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment