Skip to content

Commit

Permalink
feat: added avatar component
Browse files Browse the repository at this point in the history
  • Loading branch information
vanlooverenkoen committed Oct 7, 2024
1 parent 2c2db29 commit 008e690
Show file tree
Hide file tree
Showing 14 changed files with 255 additions and 15 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ These icons can be overriden in the theme itself. By adding your own IconData.
- search
- settings
- success
- user
- warning

# Todo
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import 'package:impaktfull_ui_example/src/component_library/components/avatar/avatar_library_variant.dart';
import 'package:impaktfull_ui_example/src/component_library/config/component_library_inputs.dart';
import 'package:impaktfull_ui_example/src/component_library/config/component_library_item.dart';

class AvatarLibraryItem extends ComponentLibraryItem {
const AvatarLibraryItem();

@override
String get title => 'ImpaktfullUiAvatar';

@override
List<ComponentLibraryVariant> getComponentVariants() {
return [
const AvatarLibraryVariant(),
];
}
}

class AvatarLibraryInputs extends ComponentLibraryInputs {
@override
List<ComponentLibraryInputItem> buildInputItems() => [];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import 'package:flutter/material.dart';
import 'package:impaktfull_ui_2/impaktfull_ui.dart';
import 'package:impaktfull_ui_example/src/component_library/components/avatar/avatar_library_item.dart';
import 'package:impaktfull_ui_example/src/component_library/config/component_library_item.dart';
import 'package:impaktfull_ui_example/src/util/network_images.dart';

class AvatarLibraryVariant
extends ComponentLibraryVariant<AvatarLibraryPrimaryInputs> {
const AvatarLibraryVariant();

@override
String get title => 'Default';

@override
List<Widget> build(BuildContext context, AvatarLibraryPrimaryInputs inputs) {
return [
ImpaktfullUiAvatar(
url: NetworkImages.profilePicture,
width: 40,
height: 40,
onTap: () => ImpaktfullUiNotification.show(title: 'Avatar tapped'),
),
ImpaktfullUiAvatar(
url: null,
width: 40,
height: 40,
onTap: () =>
ImpaktfullUiNotification.show(title: 'Empty Avatar tapped'),
),
];
}

@override
AvatarLibraryPrimaryInputs inputs() => AvatarLibraryPrimaryInputs();
}

class AvatarLibraryPrimaryInputs extends AvatarLibraryInputs {}
Original file line number Diff line number Diff line change
Expand Up @@ -88,21 +88,8 @@ class SidebarNavigationLibraryVariant
footer: Stack(
children: [
ImpaktfullUiSimpleListItem(
leadingWidgetBuilder: (context) => Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color: theme.colors.border,
width: 1,
),
),
width: 40,
height: 40,
child: const ClipOval(
child: ImpaktfullUiNetworkImage(
url: NetworkImages.profilePicture,
),
),
leadingWidgetBuilder: (context) => const ImpaktfullUiAvatar(
url: NetworkImages.profilePicture,
),
trailingWidgetBuilder: (context) => const SizedBox(width: 40),
borderRadius: ImpaktfullUiSidebarNavigationItemTheme.of(context)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:impaktfull_ui_example/src/component_library/components/asset/asset_library_item.dart';
import 'package:impaktfull_ui_example/src/component_library/components/autolayout/autolayout_library_item.dart';
import 'package:impaktfull_ui_example/src/component_library/components/avatar/avatar_library_item.dart';
import 'package:impaktfull_ui_example/src/component_library/components/badge/badge_library_item.dart';
import 'package:impaktfull_ui_example/src/component_library/components/bottom_navigation/bottom_navigation_library_item.dart';
import 'package:impaktfull_ui_example/src/component_library/components/bottom_navigation_item/bottom_navigation_item_library_item.dart';
Expand Down Expand Up @@ -37,6 +38,7 @@ class ComponentLibrary {
final List<ComponentLibraryItem> components = [
const AssetLibraryItem(),
const AutoLayoutLibraryItem(),
const AvatarLibraryItem(),
const BadgeLibraryItem(),
const BottomNavigationLibraryItem(),
const BottomNavigationItemLibraryItem(),
Expand Down
2 changes: 2 additions & 0 deletions example/lib/src/util/network_images.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
class NetworkImages {
const NetworkImages._();
static const String profilePicture = 'https://vanlooverenkoen.be/img/me.png';

static const String random = 'https://picsum.photos/300/300';
}
1 change: 1 addition & 0 deletions lib/impaktfull_ui.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
export 'src/components/app/app.dart';
export 'src/components/asset/asset_widget.dart';
export 'src/components/auto_layout/auto_layout.dart';
export 'src/components/avatar/avatar.dart';
export 'src/components/button/button.dart';
export 'src/components/bottom_navigation/bottom_navigation.dart';
export 'src/components/bottom_navigation_item/bottom_navigation_item.dart';
Expand Down
12 changes: 12 additions & 0 deletions lib/src/components/asset/asset_widget.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:impaktfull_ui_2/src/models/asset.dart';
Expand Down Expand Up @@ -35,6 +37,16 @@ class ImpaktfullUiAssetWidget extends StatelessWidget
final lottieAsset = asset.getFullLottieAsset();
final riveAsset = asset.getFullRiveAsset();
if (icon != null) {
double? size = this.size;
if (size == null) {
if (width != null && height != null) {
size = max(width!, height!);
} else if (width != null) {
size = width;
} else if (height != null) {
size = height;
}
}
return Icon(
icon,
color: color,
Expand Down
89 changes: 89 additions & 0 deletions lib/src/components/avatar/avatar.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import 'package:flutter/material.dart';
import 'package:impaktfull_ui_2/src/components/asset/asset_widget.dart';
import 'package:impaktfull_ui_2/src/components/avatar/avatar_style.dart';
import 'package:impaktfull_ui_2/src/components/network_image/network_image.dart';
import 'package:impaktfull_ui_2/src/components/theme/theme_component_builder.dart';
import 'package:impaktfull_ui_2/src/components/touch_feedback/touch_feedback.dart';
import 'package:impaktfull_ui_2/src/models/asset.dart';
import 'package:impaktfull_ui_2/src/util/descriptor/component_descriptor_mixin.dart';

export 'avatar_style.dart';

part 'avatar.describe.dart';

class ImpaktfullUiAvatar extends StatelessWidget with ComponentDescriptorMixin {
final String? url;
final ImpaktfullUiAsset? placeholderAsset;
final double width;
final double height;
final VoidCallback? onTap;
final ImpaktfullUiAvatarTheme? theme;

const ImpaktfullUiAvatar({
required this.url,
this.placeholderAsset,
this.width = 40,
this.height = 40,
this.onTap,
this.theme,
super.key,
});

@override
Widget build(BuildContext context) {
return ImpaktfullUiComponentThemeBuidler<ImpaktfullUiAvatarTheme>(
overrideComponentTheme: theme,
builder: (context, theme, componentTheme) => SizedBox(
width: width,
height: height,
child: Stack(
alignment: Alignment.center,
children: [
Container(
decoration: BoxDecoration(
border: Border.all(
color: componentTheme.colors.border,
width: 1,
),
borderRadius: componentTheme.dimens.borderRadius,
color: componentTheme.colors.background,
),
child: ClipRRect(
borderRadius: componentTheme.dimens.borderRadius,
child: Builder(builder: (context) {
if (url == null) {
return Center(
child: ImpaktfullUiAssetWidget(
asset: placeholderAsset ??
componentTheme.assets.placeholder,
color: componentTheme.colors.placeholder,
size: width / 2,
),
);
}
return ImpaktfullUiNetworkImage(
url: url!,
);
}),
),
),
if (onTap != null) ...[
Positioned.fill(
child: ImpaktfullUiTouchFeedback(
onTap: onTap,
borderRadius: componentTheme.dimens.borderRadius,
child: const ColoredBox(
color: Colors.transparent,
),
),
),
],
],
),
),
);
}

@override
String describe(BuildContext context) => _describeInstance(context, this);
}
11 changes: 11 additions & 0 deletions lib/src/components/avatar/avatar.describe.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
part of 'avatar.dart';

String _describeInstance(BuildContext context, ImpaktfullUiAvatar instance) {
final descriptor = ComponentDescriptor();
descriptor.add('url', instance.url);
descriptor.add('placeholderAsset', instance.placeholderAsset);
descriptor.add('width', instance.width);
descriptor.add('height', instance.height);
descriptor.add('theme', instance.theme);
return descriptor.describe();
}
49 changes: 49 additions & 0 deletions lib/src/components/avatar/avatar_style.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import 'package:flutter/widgets.dart';
import 'package:impaktfull_ui_2/src/models/asset.dart';
import 'package:impaktfull_ui_2/src/theme/theme.dart';

class ImpaktfullUiAvatarTheme extends ImpaktfullUiComponentTheme {
final ImpaktfullUiAvatarAssetsTheme assets;
final ImpaktfullUiAvatarColorTheme colors;
final ImpaktfullUiAvatarDimensTheme dimens;
final ImpaktfullUiAvatarTextStyleTheme textStyles;

const ImpaktfullUiAvatarTheme({
required this.assets,
required this.colors,
required this.dimens,
required this.textStyles,
});

static ImpaktfullUiAvatarTheme of(BuildContext context) =>
ImpaktfullUiTheme.of(context).components.avatar;
}

class ImpaktfullUiAvatarAssetsTheme {
final ImpaktfullUiAsset? placeholder;
const ImpaktfullUiAvatarAssetsTheme({
required this.placeholder,
});
}

class ImpaktfullUiAvatarColorTheme {
final Color border;
final Color background;
final Color placeholder;
const ImpaktfullUiAvatarColorTheme({
required this.border,
required this.background,
required this.placeholder,
});
}

class ImpaktfullUiAvatarDimensTheme {
final BorderRadiusGeometry borderRadius;
const ImpaktfullUiAvatarDimensTheme({
required this.borderRadius,
});
}

class ImpaktfullUiAvatarTextStyleTheme {
const ImpaktfullUiAvatarTextStyleTheme();
}
5 changes: 5 additions & 0 deletions lib/src/theme/asset_theme.dart
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class ImpaktfullUiAssetTheme {
search: ImpaktfullUiAsset.icon(PhosphorIcons.magnifyingGlass()),
settings: ImpaktfullUiAsset.icon(PhosphorIcons.gearSix()),
success: ImpaktfullUiAsset.icon(PhosphorIcons.checkCircle()),
user: ImpaktfullUiAsset.icon(PhosphorIcons.user()),
warning: ImpaktfullUiAsset.icon(PhosphorIcons.warning()),
),
images: images ??
Expand Down Expand Up @@ -158,6 +159,7 @@ class ImpaktfullUiIconTheme {
final ImpaktfullUiAsset list;
final ImpaktfullUiAsset logout;
final ImpaktfullUiAsset minus;
final ImpaktfullUiAsset user;
final ImpaktfullUiAsset search;
final ImpaktfullUiAsset settings;
final ImpaktfullUiAsset success;
Expand Down Expand Up @@ -190,6 +192,7 @@ class ImpaktfullUiIconTheme {
required this.search,
required this.settings,
required this.success,
required this.user,
required this.warning,
});

Expand Down Expand Up @@ -220,6 +223,7 @@ class ImpaktfullUiIconTheme {
ImpaktfullUiAsset? search,
ImpaktfullUiAsset? settings,
ImpaktfullUiAsset? success,
ImpaktfullUiAsset? user,
ImpaktfullUiAsset? warning,
}) =>
ImpaktfullUiIconTheme(
Expand Down Expand Up @@ -249,6 +253,7 @@ class ImpaktfullUiIconTheme {
search: search ?? this.search,
settings: settings ?? this.settings,
success: success ?? this.success,
user: user ?? this.user,
warning: warning ?? this.warning,
);
}
Expand Down
7 changes: 7 additions & 0 deletions lib/src/theme/component_theme.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:impaktfull_ui_2/src/components/avatar/avatar.dart';
import 'package:impaktfull_ui_2/src/components/badge/badge.dart';
import 'package:impaktfull_ui_2/src/components/bottom_navigation/bottom_navigation.dart';
import 'package:impaktfull_ui_2/src/components/bottom_navigation_item/bottom_navigation_item.dart';
Expand Down Expand Up @@ -41,6 +42,7 @@ abstract class ImpaktfullUiComponentTheme {
}

class ImpaktfullUiComponentsTheme {
final ImpaktfullUiAvatarTheme avatar;
final ImpaktfullUiBadgeTheme badge;
final ImpaktfullUiBottomNavigationTheme bottomNavigation;
final ImpaktfullUiBottomNavigationItemTheme bottomNavigationItem;
Expand Down Expand Up @@ -79,6 +81,7 @@ class ImpaktfullUiComponentsTheme {
final ImpaktfullUiTooltipTheme tooltip;

ImpaktfullUiComponentsTheme({
required this.avatar,
required this.badge,
required this.bottomNavigation,
required this.bottomNavigationItem,
Expand Down Expand Up @@ -118,6 +121,7 @@ class ImpaktfullUiComponentsTheme {
});

ImpaktfullUiComponentsTheme copyWith({
ImpaktfullUiAvatarTheme? avatar,
ImpaktfullUiBadgeTheme? badge,
ImpaktfullUiBottomNavigationTheme? bottomNavigation,
ImpaktfullUiBottomNavigationItemTheme? bottomNavigationItem,
Expand Down Expand Up @@ -156,6 +160,7 @@ class ImpaktfullUiComponentsTheme {
ImpaktfullUiTooltipTheme? tooltip,
}) =>
ImpaktfullUiComponentsTheme(
avatar: avatar ?? this.avatar,
badge: badge ?? this.badge,
bottomNavigation: bottomNavigation ?? this.bottomNavigation,
bottomNavigationItem: bottomNavigationItem ?? this.bottomNavigationItem,
Expand Down Expand Up @@ -198,6 +203,8 @@ class ImpaktfullUiComponentsTheme {
static T of<T extends ImpaktfullUiComponentTheme>(BuildContext context) {
if (T == ImpaktfullUiBadgeTheme) {
return ImpaktfullUiBadgeTheme.of(context) as T;
} else if (T == ImpaktfullUiAvatarTheme) {
return ImpaktfullUiAvatarTheme.of(context) as T;
} else if (T == ImpaktfullUiBottomNavigationTheme) {
return ImpaktfullUiBottomNavigationTheme.of(context) as T;
} else if (T == ImpaktfullUiBottomNavigationItemTheme) {
Expand Down
Loading

0 comments on commit 008e690

Please sign in to comment.