diff --git a/example/lib/pages/components/avatar_example.dart b/example/lib/pages/components/avatar_example.dart index 39f42a8f..b32b4c14 100644 --- a/example/lib/pages/components/avatar_example.dart +++ b/example/lib/pages/components/avatar_example.dart @@ -202,7 +202,8 @@ class AvatarExample extends StatelessWidget { children: [ ZetaAvatar.image( size: size, - upperBadge: ZetaIndicator.notification(value: 3), + upperBadge: + ZetaAvatarBadge.notification(value: 3), ), const SizedBox(height: 20), ], @@ -217,7 +218,8 @@ class AvatarExample extends StatelessWidget { ZetaAvatar.image( size: size, borderColor: Zeta.of(context).colors.green, - upperBadge: ZetaIndicator.notification(value: 3), + upperBadge: + ZetaAvatarBadge.notification(value: 3), ), const SizedBox(height: 20), ], @@ -231,7 +233,8 @@ class AvatarExample extends StatelessWidget { children: [ ZetaAvatar.image( size: size, - upperBadge: ZetaIndicator.notification(value: 3), + upperBadge: + ZetaAvatarBadge.notification(value: 3), image: image, ), const SizedBox(height: 20), @@ -247,7 +250,8 @@ class AvatarExample extends StatelessWidget { ZetaAvatar.image( size: size, borderColor: Zeta.of(context).colors.green, - upperBadge: ZetaIndicator.notification(value: 3), + upperBadge: + ZetaAvatarBadge.notification(value: 3), image: image, ), const SizedBox(height: 20), @@ -294,7 +298,8 @@ class AvatarExample extends StatelessWidget { ZetaAvatar.initials( size: size, initials: 'AB', - upperBadge: ZetaIndicator.notification(value: 3), + upperBadge: + ZetaAvatarBadge.notification(value: 3), ), const SizedBox(height: 20), ], @@ -310,7 +315,8 @@ class AvatarExample extends StatelessWidget { size: size, initials: 'AB', borderColor: Zeta.of(context).colors.green, - upperBadge: ZetaIndicator.notification(value: 3), + upperBadge: + ZetaAvatarBadge.notification(value: 3), ), const SizedBox(height: 20), ], @@ -355,7 +361,7 @@ class AvatarExample extends StatelessWidget { children: [ ZetaAvatar.image( size: size, - lowerBadge: ZetaIndicator.icon(), + lowerBadge: ZetaAvatarBadge.icon(), ), const SizedBox(height: 20), ], @@ -370,7 +376,7 @@ class AvatarExample extends StatelessWidget { ZetaAvatar.image( size: size, borderColor: Zeta.of(context).colors.green, - lowerBadge: ZetaIndicator.icon(), + lowerBadge: ZetaAvatarBadge.icon(), ), const SizedBox(height: 20), ], @@ -384,7 +390,7 @@ class AvatarExample extends StatelessWidget { children: [ ZetaAvatar.image( size: size, - lowerBadge: ZetaIndicator.icon(), + lowerBadge: ZetaAvatarBadge.icon(), image: image, ), const SizedBox(height: 20), @@ -400,7 +406,7 @@ class AvatarExample extends StatelessWidget { ZetaAvatar.image( size: size, borderColor: Zeta.of(context).colors.green, - lowerBadge: ZetaIndicator.icon(), + lowerBadge: ZetaAvatarBadge.icon(), image: image, ), const SizedBox(height: 20), @@ -447,7 +453,7 @@ class AvatarExample extends StatelessWidget { ZetaAvatar.initials( size: size, initials: 'AB', - lowerBadge: ZetaIndicator.icon(), + lowerBadge: ZetaAvatarBadge.icon(), ), const SizedBox(height: 20), ], @@ -463,7 +469,7 @@ class AvatarExample extends StatelessWidget { size: size, initials: 'AB', borderColor: Zeta.of(context).colors.green, - lowerBadge: ZetaIndicator.icon(), + lowerBadge: ZetaAvatarBadge.icon(), ), const SizedBox(height: 20), ], @@ -509,8 +515,9 @@ class AvatarExample extends StatelessWidget { ZetaAvatar.image( size: size, image: image, - upperBadge: ZetaIndicator.notification(value: 3), - lowerBadge: ZetaIndicator.icon(), + upperBadge: + ZetaAvatarBadge.notification(value: 3), + lowerBadge: ZetaAvatarBadge.icon(), ), const SizedBox(height: 20), ], @@ -526,8 +533,9 @@ class AvatarExample extends StatelessWidget { size: size, image: image, borderColor: Zeta.of(context).colors.green, - upperBadge: ZetaIndicator.notification(value: 3), - lowerBadge: ZetaIndicator.icon(), + upperBadge: + ZetaAvatarBadge.notification(value: 3), + lowerBadge: ZetaAvatarBadge.icon(), ), const SizedBox(height: 20), ], @@ -541,8 +549,9 @@ class AvatarExample extends StatelessWidget { ZetaAvatar.initials( size: size, initials: 'AB', - upperBadge: ZetaIndicator.notification(value: 3), - lowerBadge: ZetaIndicator.icon(), + upperBadge: + ZetaAvatarBadge.notification(value: 3), + lowerBadge: ZetaAvatarBadge.icon(), ), const SizedBox(height: 20), ], @@ -558,8 +567,9 @@ class AvatarExample extends StatelessWidget { size: size, initials: 'AB', borderColor: Zeta.of(context).colors.green, - upperBadge: ZetaIndicator.notification(value: 3), - lowerBadge: ZetaIndicator.icon(), + upperBadge: + ZetaAvatarBadge.notification(value: 3), + lowerBadge: ZetaAvatarBadge.icon(), ), const SizedBox(height: 20), ], @@ -580,15 +590,23 @@ class AvatarExample extends StatelessWidget { extension on ZetaAvatarSize { double get pixelSize { switch (this) { + case ZetaAvatarSize.xxxl: + return ZetaSpacing.x50; + case ZetaAvatarSize.xxl: + return ZetaSpacing.x30; case ZetaAvatarSize.xl: - return ZetaSpacing.x16; + return ZetaSpacing.x20; case ZetaAvatarSize.l: - return ZetaSpacing.x12; + return ZetaSpacing.x16; case ZetaAvatarSize.m: - return ZetaSpacing.x10; + return ZetaSpacing.x12; case ZetaAvatarSize.s: - return ZetaSpacing.x8; + return ZetaSpacing.x10; case ZetaAvatarSize.xs: + return ZetaSpacing.x9; + case ZetaAvatarSize.xxs: + return ZetaSpacing.x8; + case ZetaAvatarSize.xxxs: return ZetaSpacing.x6; } } diff --git a/example/widgetbook/pages/components/avatar_widgetbook.dart b/example/widgetbook/pages/components/avatar_widgetbook.dart index f533cf08..189fd7c9 100644 --- a/example/widgetbook/pages/components/avatar_widgetbook.dart +++ b/example/widgetbook/pages/components/avatar_widgetbook.dart @@ -6,6 +6,7 @@ import '../../test/test_components.dart'; Widget avatarUseCase(BuildContext context) { final Widget image = Image.asset('assets/Omer.jpg', fit: BoxFit.cover); + final colors = Zeta.of(context).colors; return WidgetbookTestWidget( widget: ZetaAvatar( @@ -15,12 +16,29 @@ Widget avatarUseCase(BuildContext context) { options: ZetaAvatarSize.values, labelBuilder: (value) => value.name.split('.').last.toUpperCase(), ), - lowerBadge: context.knobs.boolean(label: 'Status Badge', initialValue: false) ? ZetaIndicator.icon() : null, - borderColor: context.knobs.colorOrNull(label: 'Outline', initialValue: null), upperBadge: - context.knobs.boolean(label: 'Notification Badge', initialValue: false) ? ZetaIndicator.notification() : null, - initials: context.knobs.stringOrNull(label: 'Initials', initialValue: null), - backgroundColor: context.knobs.colorOrNull(label: 'Background color'), + context.knobs.boolean(label: 'Status Badge', initialValue: false) + ? ZetaAvatarBadge.icon( + icon: ZetaIcons.close_round, + iconColor: Colors.white, + color: Color.fromRGBO(141, 149, 163, 1), + ) + : null, + borderColor: context.knobs.colorOrNull( + label: 'Outline', + ), + lowerBadge: context.knobs + .boolean(label: 'Notification Badge', initialValue: false) + ? ZetaAvatarBadge.notification( + value: 99, + color: colors.negative, + ) + : null, + initials: + context.knobs.stringOrNull(label: 'Initials', initialValue: null), + backgroundColor: context.knobs.colorOrNull( + label: 'Background color', + ), ), ); } diff --git a/lib/src/components/avatars/avatar.dart b/lib/src/components/avatars/avatar.dart index c1d4bf6a..fd6df0ff 100644 --- a/lib/src/components/avatars/avatar.dart +++ b/lib/src/components/avatars/avatar.dart @@ -4,20 +4,32 @@ import '../../../zeta_flutter.dart'; /// [ZetaAvatar] size enum ZetaAvatarSize { - /// [xl] 64 pixels + /// [xxxl] 200 pixels + xxxl, + + /// [xxl] 120 pixels + xxl, + + /// [xl] 80 pixels xl, - /// [l] 48 pixels + /// [l] 64 pixels l, - /// [m] 40 pixels + /// [m] 48 pixels m, - /// [s] 32 pixels + /// [s] 40 pixels s, - /// [xs] 24 pixels + /// [xs] 36 pixels xs, + + /// [xxs] 32 pixels + xxs, + + /// [xxxs] 24 pixels + xxxs, } /// ZetaAvatar component @@ -86,12 +98,13 @@ class ZetaAvatar extends StatelessWidget { final Color? borderColor; /// Status badge shown at lower right corner of avatar. - final ZetaIndicator? lowerBadge; + final ZetaAvatarBadge? lowerBadge; /// Notification Badge shown at top right corner of avatar. - final ZetaIndicator? upperBadge; + final ZetaAvatarBadge? upperBadge; - bool get _showPlaceholder => image == null && (initials == null || initials!.isEmpty); + bool get _showPlaceholder => + image == null && (initials == null || initials!.isEmpty); @override Widget build(BuildContext context) { @@ -99,29 +112,28 @@ class ZetaAvatar extends StatelessWidget { final borderSize = size.borderSize; final sizePixels = size.pixelSize; - final contentSizePixels = size.pixelSize - (borderColor != null ? size.borderSize * 2 : 0); + final contentSizePixels = size.pixelSize; + + final innerChild = image ?? + (initials != null + ? Center( + child: Text( + size == ZetaAvatarSize.xs + ? initials!.substring(0, 1) + : initials!, + style: TextStyle( + fontSize: size.fontSize, + letterSpacing: -0.5, + color: backgroundColor!.onColor, + ), + ), + ) + : null); final innerContent = ClipRRect( borderRadius: BorderRadius.circular(64), clipBehavior: Clip.hardEdge, - child: image ?? - (_showPlaceholder - ? Container( - transform: Matrix4.translationValues(-contentSizePixels * 0.2, -contentSizePixels * 0.1, 0), - child: IconTheme( - data: IconThemeData( - color: Zeta.of(context).colors.cool, - size: contentSizePixels * 1.4, - ), - child: const Icon(ZetaIcons.user_round), - ), - ) - : Center( - child: Text( - size == ZetaAvatarSize.xs ? initials!.substring(0, 1) : initials!, - style: TextStyle(fontSize: size.fontSize, letterSpacing: -0.5), - ), - )), + child: innerChild, ); return Stack( @@ -131,39 +143,56 @@ class ZetaAvatar extends StatelessWidget { width: sizePixels, height: sizePixels, decoration: BoxDecoration( - border: borderColor != null ? Border.all(color: borderColor!, width: borderSize / ZetaSpacing.x0_5) : null, + border: borderColor != null + ? Border.all(color: borderColor!, width: 0) + : null, borderRadius: ZetaRadius.full, - color: backgroundColor ?? (_showPlaceholder ? zetaColors.surfacePrimary : zetaColors.cool.shade20), + color: backgroundColor ?? + (_showPlaceholder + ? zetaColors.surfacePrimary + : zetaColors.cool.shade20), ), child: borderColor != null ? Container( width: contentSizePixels, height: contentSizePixels, decoration: BoxDecoration( - color: _showPlaceholder ? backgroundColor ?? zetaColors.surfaceHovered : null, - border: Border.all(color: zetaColors.surfacePrimary, width: borderSize / ZetaSpacing.x0_5), + color: backgroundColor ?? zetaColors.surfaceHovered, + border: Border.all(color: borderColor!, width: borderSize), + borderRadius: ZetaRadius.full, + ), + child: ClipRRect( borderRadius: ZetaRadius.full, + clipBehavior: Clip.hardEdge, + child: innerContent, ), - child: ClipRRect(borderRadius: ZetaRadius.full, clipBehavior: Clip.hardEdge, child: innerContent), ) : DecoratedBox( decoration: BoxDecoration( borderRadius: ZetaRadius.full, color: backgroundColor ?? zetaColors.surfaceHovered, ), - child: innerContent, + child: ClipRRect( + borderRadius: ZetaRadius.full, + clipBehavior: Clip.hardEdge, + child: innerContent, + ), ), ), if (upperBadge != null) Positioned( right: 1, - child: upperBadge!.copyWith(size: size.indicatorSize), + child: upperBadge!.copyWith( + size: size, + ), ), if (lowerBadge != null) Positioned( right: 1, bottom: 1, - child: lowerBadge!.copyWith(size: size.indicatorSize), + child: lowerBadge!.copyWith( + size: size, + ), ), ], ); @@ -175,8 +204,8 @@ class ZetaAvatar extends StatelessWidget { properties ..add(DiagnosticsProperty('size', size)) ..add(DiagnosticsProperty('name', initials)) - ..add(DiagnosticsProperty('specialStatus', lowerBadge)) - ..add(DiagnosticsProperty('badge', upperBadge)) + ..add(DiagnosticsProperty('specialStatus', lowerBadge)) + ..add(DiagnosticsProperty('badge', upperBadge)) ..add(DiagnosticsProperty('backgroundColor', backgroundColor)) ..add(ColorProperty('statusColor', borderColor)); } @@ -185,35 +214,32 @@ class ZetaAvatar extends StatelessWidget { extension on ZetaAvatarSize { double get pixelSize { switch (this) { + case ZetaAvatarSize.xxxl: + return ZetaSpacing.x50; + case ZetaAvatarSize.xxl: + return ZetaSpacing.x30; case ZetaAvatarSize.xl: - return ZetaSpacing.x16; + return ZetaSpacing.x20; case ZetaAvatarSize.l: - return ZetaSpacing.x12; + return ZetaSpacing.x16; case ZetaAvatarSize.m: - return ZetaSpacing.x10; + return ZetaSpacing.x12; case ZetaAvatarSize.s: - return ZetaSpacing.x8; + return ZetaSpacing.x10; case ZetaAvatarSize.xs: + return ZetaSpacing.x9; + case ZetaAvatarSize.xxs: + return ZetaSpacing.x8; + case ZetaAvatarSize.xxxs: return ZetaSpacing.x6; } } - ZetaWidgetSize get indicatorSize { - switch (this) { - case ZetaAvatarSize.xl: - case ZetaAvatarSize.l: - case ZetaAvatarSize.m: - return ZetaWidgetSize.large; - case ZetaAvatarSize.s: - return ZetaWidgetSize.medium; - - case ZetaAvatarSize.xs: - return ZetaWidgetSize.small; - } - } - double get borderSize { switch (this) { + case ZetaAvatarSize.xxxl: + return 11; + case ZetaAvatarSize.xxl: case ZetaAvatarSize.xl: case ZetaAvatarSize.l: case ZetaAvatarSize.m: @@ -221,21 +247,158 @@ extension on ZetaAvatarSize { case ZetaAvatarSize.s: case ZetaAvatarSize.xs: + case ZetaAvatarSize.xxs: + case ZetaAvatarSize.xxxs: return ZetaSpacing.x0_5; } } double get fontSize { - switch (this) { - case ZetaAvatarSize.xl: - return ZetaSpacing.x5; - case ZetaAvatarSize.l: - return ZetaSpacing.x4; - case ZetaAvatarSize.m: - return ZetaSpacing.x3_5; - case ZetaAvatarSize.s: - case ZetaAvatarSize.xs: - return ZetaSpacing.x3; - } + return pixelSize * 4 / 9; + } +} + +/// Enum of types for [ZetaAvatarBadge] +enum ZetaAvatarBadgeType { + /// Shows an icon on [ZetaAvatarBadge]. Defaults to [ZetaIcons.star_round]. + icon, + + /// Shows a number on [ZetaAvatarBadge] from provided [ZetaAvatarBadge.value]. + notification, +} + +/// ZetaAvatarBadge component + +class ZetaAvatarBadge extends StatelessWidget { + /// Constructor for [ZetaAvatarBadge] + const ZetaAvatarBadge({ + super.key, + this.color = Colors.grey, + this.type = ZetaAvatarBadgeType.notification, + this.icon, + this.value, + this.iconColor, + }) : size = ZetaAvatarSize.xxxl; + + const ZetaAvatarBadge._({ + super.key, + required this.color, + required this.size, + required this.type, + this.icon, + this.value, + this.iconColor, + }); + + /// Constructs [ZetaAvatarBadge] with icon + const ZetaAvatarBadge.icon({ + super.key, + this.color = Colors.grey, + this.icon = ZetaIcons.star_round, + this.iconColor, + }) : value = null, + size = ZetaAvatarSize.xxxl, + type = ZetaAvatarBadgeType.icon; + + /// Constructs [ZetaAvatarBadge] with notifications + + const ZetaAvatarBadge.notification({ + super.key, + required this.value, + this.color = Colors.red, + }) : size = ZetaAvatarSize.xxxl, + icon = null, + iconColor = null, + type = ZetaAvatarBadgeType.notification; + + /// Size of badge + final ZetaAvatarSize size; + + /// Type of badge + final ZetaAvatarBadgeType type; + + /// Background color for badge + final Color color; + + /// Icon of badge + final IconData? icon; + + /// Icon color for badge + final Color? iconColor; + + /// Notification value for badge + final double? value; + + /// Returns copy of [ZetaAvatarBadge] + ZetaAvatarBadge copyWith({ + Color? color, + ZetaAvatarSize? size, + IconData? icon, + Color? iconColor, + double? value, + ZetaAvatarBadgeType? type, + }) { + return ZetaAvatarBadge._( + color: color ?? this.color, + size: size ?? this.size, + icon: icon ?? this.icon, + type: type ?? this.type, + value: value ?? this.value, + iconColor: iconColor ?? this.iconColor, + key: key, + ); + } + + @override + Widget build(BuildContext context) { + final badgeSize = _getContainerSize(); + final borderSize = _getBorderSize(); + + final innerContent = value != null + ? Text( + '$value+', + style: TextStyle(color: color.onColor, fontSize: badgeSize / 2), + ) + : icon != null + ? Icon( + icon, + size: badgeSize - borderSize, + color: iconColor ?? color.onColor, + ) + : null; + + return Container( + width: badgeSize + ZetaSpacing.x1, + height: badgeSize + ZetaSpacing.x1, + decoration: BoxDecoration( + color: color, + borderRadius: ZetaRadius.full, + border: Border.all( + width: borderSize, + color: Colors.white, + ), + ), + child: Center(child: innerContent), + ); + } + + double _getContainerSize() { + return size.pixelSize / 3; + } + + double _getBorderSize() { + return size.pixelSize / 48; + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(ColorProperty('color', color)) + ..add(EnumProperty('size', size)) + ..add(EnumProperty('type', type)) + ..add(DiagnosticsProperty('icon', icon)) + ..add(ColorProperty('iconColor', iconColor)) + ..add(DoubleProperty('value', value)); } } diff --git a/lib/src/components/buttons/button_group.dart b/lib/src/components/buttons/button_group.dart index a3ddf280..82c9d5ac 100644 --- a/lib/src/components/buttons/button_group.dart +++ b/lib/src/components/buttons/button_group.dart @@ -253,7 +253,7 @@ class _ZetaGroupButtonState extends State { widget.rounded ? ZetaIcons.expand_more_round : ZetaIcons.expand_more_sharp, - size: ZetaSpacing.x5), + size: ZetaSpacing.x5,), ].divide(const SizedBox(width: ZetaSpacing.x1)).toList(), ).paddingAll(_padding), ), diff --git a/lib/src/theme/tokens.dart b/lib/src/theme/tokens.dart index caecce51..abdcdb88 100644 --- a/lib/src/theme/tokens.dart +++ b/lib/src/theme/tokens.dart @@ -98,6 +98,12 @@ class ZetaSpacing { /// 96dp space. static const double xxxl = spacingBaseMultiplier * 24; + + /// 120dp space + static const double x30 = spacingBaseMultiplier * 30; + + /// 200dp space + static const double x50 = spacingBaseMultiplier * 50; } /// Tokens used for Border Radius. @@ -106,16 +112,20 @@ class ZetaRadius { static const BorderRadius none = BorderRadius.zero; /// Smallest amount of border radius; 4px radius. - static const BorderRadius minimal = BorderRadius.all(Radius.circular(ZetaSpacing.xxs)); + static const BorderRadius minimal = + BorderRadius.all(Radius.circular(ZetaSpacing.xxs)); /// Border radius used when rounded parameter is true; 8px radius. - static const BorderRadius rounded = BorderRadius.all(Radius.circular(ZetaSpacing.xs)); + static const BorderRadius rounded = + BorderRadius.all(Radius.circular(ZetaSpacing.xs)); /// Large border radius; 16px radius. - static const BorderRadius large = BorderRadius.all(Radius.circular(ZetaSpacing.b)); + static const BorderRadius large = + BorderRadius.all(Radius.circular(ZetaSpacing.b)); /// Wide border radius; 24px radius. - static const BorderRadius wide = BorderRadius.all(Radius.circular(ZetaSpacing.m)); + static const BorderRadius wide = + BorderRadius.all(Radius.circular(ZetaSpacing.m)); /// Largest amount of border radius; 360px radius. static const BorderRadius full = BorderRadius.all(Radius.circular(360)); diff --git a/lib/zeta_flutter.dart b/lib/zeta_flutter.dart index 14a1ff03..470ce04e 100644 --- a/lib/zeta_flutter.dart +++ b/lib/zeta_flutter.dart @@ -25,11 +25,8 @@ export 'src/components/checkbox/checkbox.dart'; export 'src/components/chips/chip.dart'; export 'src/components/date_input/date_input.dart'; export 'src/components/dial_pad/dial_pad.dart'; -<<<<<<< HEAD -======= export 'src/components/dialog/dialog.dart'; export 'src/components/dropdown/dropdown.dart'; ->>>>>>> 7a5dabb51a06204f87ee266b98c981600fed89a9 export 'src/components/list_item/list_item.dart'; export 'src/components/navigation bar/navigation_bar.dart'; export 'src/components/pagination/pagination.dart';