Instantly share code, notes, and snippets.
Created
January 24, 2025 10:51
-
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 hawkkiller/2b0e759256b1022cd1c1c2f00d9dfcaf to your computer and use it in GitHub Desktop.
Different buttons for design system
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
| import 'package:ui/ui.dart'; | |
| sealed class UiButton extends StatelessWidget { | |
| const UiButton({super.key}); | |
| const factory UiButton.primary({ | |
| required String label, | |
| required VoidCallback? onPressed, | |
| Widget? icon, | |
| bool isEnabled, | |
| bool isLoading, | |
| IconAlignment iconAlignment, | |
| Key? key, | |
| }) = _UiButtonPrimary; | |
| const factory UiButton.secondary({ | |
| required String label, | |
| required VoidCallback? onPressed, | |
| Widget? icon, | |
| bool isEnabled, | |
| bool isLoading, | |
| IconAlignment iconAlignment, | |
| Key? key, | |
| }) = _UiButtonSecondary; | |
| const factory UiButton.tertiary({ | |
| required String label, | |
| required VoidCallback? onPressed, | |
| bool isEnabled, | |
| bool isLoading, | |
| Widget? icon, | |
| IconAlignment iconAlignment, | |
| Key? key, | |
| }) = _TertiaryUiButton; | |
| const factory UiButton.icon({ | |
| required Widget icon, | |
| required VoidCallback? onPressed, | |
| bool isEnabled, | |
| bool isLoading, | |
| Key? key, | |
| }) = _IconUiButton; | |
| } | |
| class _UiButtonPrimary extends UiButton { | |
| const _UiButtonPrimary({ | |
| required this.label, | |
| this.icon, | |
| this.onPressed, | |
| this.isEnabled = true, | |
| this.isLoading = false, | |
| this.iconAlignment = IconAlignment.start, | |
| super.key, | |
| }); | |
| final String label; | |
| final IconAlignment iconAlignment; | |
| final bool isEnabled; | |
| final bool isLoading; | |
| final Widget? icon; | |
| final VoidCallback? onPressed; | |
| /// Returns true if the button is enabled. | |
| bool get _isEnabled => onPressed != null && !isLoading && isEnabled; | |
| @override | |
| Widget build(BuildContext context) => FilledButton.icon( | |
| label: _ContentLoadingSwitch( | |
| _ButtonContent(label: label, icon: icon, iconAlignment: iconAlignment), | |
| isLoading, | |
| ), | |
| onPressed: _isEnabled ? onPressed : null, | |
| icon: icon, | |
| iconAlignment: iconAlignment, | |
| ); | |
| } | |
| class _UiButtonSecondary extends UiButton { | |
| const _UiButtonSecondary({ | |
| required this.label, | |
| this.icon, | |
| this.onPressed, | |
| this.isEnabled = true, | |
| this.isLoading = false, | |
| this.iconAlignment = IconAlignment.start, | |
| super.key, | |
| }); | |
| final String label; | |
| final IconAlignment iconAlignment; | |
| final bool isEnabled; | |
| final bool isLoading; | |
| final Widget? icon; | |
| final VoidCallback? onPressed; | |
| /// Returns true if the button is enabled. | |
| bool get _isEnabled => onPressed != null && !isLoading && isEnabled; | |
| @override | |
| Widget build(BuildContext context) => OutlinedButton.icon( | |
| label: _ContentLoadingSwitch( | |
| _ButtonContent(label: label, icon: icon, iconAlignment: iconAlignment), | |
| isLoading, | |
| ), | |
| onPressed: _isEnabled ? onPressed : null, | |
| icon: icon, | |
| iconAlignment: iconAlignment, | |
| ); | |
| } | |
| class _TertiaryUiButton extends UiButton { | |
| const _TertiaryUiButton({ | |
| required this.label, | |
| this.icon, | |
| this.onPressed, | |
| this.isEnabled = true, | |
| this.isLoading = false, | |
| this.iconAlignment = IconAlignment.start, | |
| super.key, | |
| }); | |
| final String label; | |
| final IconAlignment iconAlignment; | |
| final bool isEnabled; | |
| final bool isLoading; | |
| final Widget? icon; | |
| final VoidCallback? onPressed; | |
| /// Returns true if the button is enabled. | |
| bool get _isEnabled => onPressed != null && !isLoading && isEnabled; | |
| @override | |
| Widget build(BuildContext context) => TextButton.icon( | |
| label: _ContentLoadingSwitch( | |
| _ButtonContent(label: label, icon: icon, iconAlignment: iconAlignment), | |
| isLoading, | |
| ), | |
| onPressed: _isEnabled ? onPressed : null, | |
| ); | |
| } | |
| class _IconUiButton extends UiButton { | |
| const _IconUiButton({ | |
| required this.icon, | |
| required this.onPressed, | |
| this.isEnabled = true, | |
| this.isLoading = false, | |
| super.key, | |
| }); | |
| final Widget icon; | |
| final bool isEnabled; | |
| final bool isLoading; | |
| final VoidCallback? onPressed; | |
| /// Returns true if the button is enabled. | |
| bool get _isEnabled => onPressed != null && !isLoading && isEnabled; | |
| @override | |
| Widget build(BuildContext context) => IconButton( | |
| icon: _ContentLoadingSwitch(icon, isLoading), | |
| onPressed: _isEnabled ? onPressed : null, | |
| ); | |
| } | |
| class _ButtonContent extends StatelessWidget { | |
| const _ButtonContent({ | |
| required this.label, | |
| required this.iconAlignment, | |
| this.icon, | |
| }); | |
| final String label; | |
| final Widget? icon; | |
| final IconAlignment iconAlignment; | |
| @override | |
| Widget build(BuildContext context) => Row( | |
| mainAxisSize: MainAxisSize.min, | |
| spacing: 8, | |
| children: iconAlignment == IconAlignment.start | |
| ? [if (icon != null) icon!, Text(label)] | |
| : [Text(label), if (icon != null) const SizedBox(width: 8)], | |
| ); | |
| } | |
| class _ContentLoadingSwitch extends StatelessWidget { | |
| const _ContentLoadingSwitch(this.content, this.isLoading); | |
| final Widget content; | |
| final bool isLoading; | |
| @override | |
| Widget build(BuildContext context) => Stack( | |
| alignment: Alignment.center, | |
| children: [ | |
| Visibility( | |
| visible: !isLoading, | |
| maintainState: true, | |
| maintainSize: true, | |
| maintainAnimation: true, | |
| maintainInteractivity: true, | |
| maintainSemantics: true, | |
| child: content, | |
| ), | |
| Visibility( | |
| visible: isLoading, | |
| child: SizedBox.square( | |
| dimension: 24, | |
| child: UiProgressIndicator(), | |
| ), | |
| ), | |
| ], | |
| ); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment