Skip to content

Commit

Permalink
feat: [MDS-377] Create avatar widget (#22)
Browse files Browse the repository at this point in the history
* feat: [MDS-377] Avatar progress

* feat: [MDS-377] Create avatar widget

* feat: [MDS-377] Finalize MoonAvatar story

* chore: update .gitignore
  • Loading branch information
Kypsis authored Feb 10, 2023
1 parent 307deae commit 57d0a0d
Show file tree
Hide file tree
Showing 21 changed files with 716 additions and 41 deletions.
1 change: 1 addition & 0 deletions example/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ app.*.symbols
app.*.map.json

# Android Studio will place build artifacts here
/pubspec.lock
/android/app/debug
/android/app/profile
/android/app/release
Expand Down
Binary file added example/assets/images/placeholder-640x359.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 0 additions & 1 deletion example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Moon Design for Flutter',
color: Colors.white,
home: HomePage(),
);
}
Expand Down
2 changes: 1 addition & 1 deletion example/lib/src/storybook/common/options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ List<Color> colorTable(BuildContext context) => [
context.moonColors!.chiChi100,
context.moonColors!.chiChi60,
context.moonColors!.chiChi10,
context.moonColors!.roshi60,
context.moonColors!.roshi100,
context.moonColors!.roshi60,
context.moonColors!.roshi10,
context.moonColors!.frieza100,
context.moonColors!.frieza60,
Expand Down
110 changes: 110 additions & 0 deletions example/lib/src/storybook/stories/avatar.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import 'package:example/src/storybook/common/options.dart';
import 'package:example/src/storybook/common/widgets/text_divider.dart';
import 'package:flutter/material.dart';
import 'package:moon_design/moon_design.dart';
import 'package:storybook_flutter/storybook_flutter.dart';

class AvatarStory extends Story {
AvatarStory()
: super(
name: "Avatar",
builder: (context) {
final avatarSizesKnob = context.knobs.options(
label: "avatarSize",
description: "Avatar size variants.",
initial: MoonAvatarSize.md,
options: const [
Option(label: "xs", value: MoonAvatarSize.xs),
Option(label: "sm", value: MoonAvatarSize.sm),
Option(label: "md", value: MoonAvatarSize.md),
Option(label: "lg", value: MoonAvatarSize.lg),
Option(label: "xl", value: MoonAvatarSize.xl),
Option(label: "x2l", value: MoonAvatarSize.x2l),
],
);

final customLabelTextKnob = context.knobs.text(
label: "Custom label text",
initial: "MD",
);

final avatarBackgroundColorKnob = context.knobs.options(
label: "backgroundColor",
description: "MoonColors variants for avatar background.",
initial: 5, // bulma
options: colorOptions,
);

final backgroundColor = colorTable(context)[avatarBackgroundColorKnob];

final borderRadiusKnob = context.knobs.sliderInt(
max: 32,
initial: 8,
label: "borderRadius",
description: "Border radius for the avatar.",
);

final showBadgeKnob = context.knobs.boolean(
label: "showBadge",
description: "Show avatar badge.",
initial: true,
);

final avatarBadgeAlignmentKnob = context.knobs.options(
label: "badgeAlignment",
description: "Avatar badge alignment.",
initial: MoonBadgeAlignment.bottomRight,
options: const [
Option(label: "topLeft", value: MoonBadgeAlignment.topLeft),
Option(label: "topRight", value: MoonBadgeAlignment.topRight),
Option(label: "bottomLeft", value: MoonBadgeAlignment.bottomLeft),
Option(label: "bottomRight", value: MoonBadgeAlignment.bottomRight),
],
);

final badgeColorKnob = context.knobs.options(
label: "badgeColor",
description: "MoonColors variants for the avatar badge.",
initial: 18, // roshi100
options: colorOptions,
);

final badgeColor = colorTable(context)[badgeColorKnob];

return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(height: 64),
const TextDivider(text: "Customisable avatar"),
const SizedBox(height: 32),
MoonAvatar(
avatarSize: avatarSizesKnob,
borderRadius: BorderRadius.circular(borderRadiusKnob.toDouble()),
backgroundColor: backgroundColor,
showBadge: showBadgeKnob,
badgeColor: badgeColor,
badgeAlignment: avatarBadgeAlignmentKnob,
child: Padding(
padding: const EdgeInsets.only(top: 1.0),
child: Text(customLabelTextKnob),
),
),
const SizedBox(height: 40),
const TextDivider(text: "Preset avatar with picture background"),
const SizedBox(height: 32),
MoonAvatar(
avatarSize: avatarSizesKnob,
backgroundColor: backgroundColor,
showBadge: showBadgeKnob,
badgeColor: badgeColor,
badgeAlignment: avatarBadgeAlignmentKnob,
backgroundImage: const AssetImage("images/placeholder-640x359.png"),
),
const SizedBox(height: 64),
],
),
);
},
);
}
20 changes: 10 additions & 10 deletions example/lib/src/storybook/stories/button.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,23 +29,23 @@ class ButtonStory extends Story {
initial: true,
);

final showBorderRadiusKnob = context.knobs.sliderInt(
final borderRadiusKnob = context.knobs.sliderInt(
max: 28,
initial: 8,
label: "borderRadius",
description: "Border radius for base MoonButton.",
);

final buttonSizesKnob = context.knobs.options(
label: "buttonSize",
label: "MoonButtonSize",
description: "Button size variants.",
initial: ButtonSize.md,
initial: MoonButtonSize.md,
options: const [
Option(label: "xs", value: ButtonSize.xs),
Option(label: "sm", value: ButtonSize.sm),
Option(label: "md", value: ButtonSize.md),
Option(label: "lg", value: ButtonSize.lg),
Option(label: "xl", value: ButtonSize.xl)
Option(label: "xs", value: MoonButtonSize.xs),
Option(label: "sm", value: MoonButtonSize.sm),
Option(label: "md", value: MoonButtonSize.md),
Option(label: "lg", value: MoonButtonSize.lg),
Option(label: "xl", value: MoonButtonSize.xl)
],
);

Expand Down Expand Up @@ -103,7 +103,7 @@ class ButtonStory extends Story {
const SizedBox(height: 32),
MoonButton(
onTap: showDisabledKnob ? null : () {},
borderRadius: BorderRadius.circular(showBorderRadiusKnob.toDouble()),
borderRadius: BorderRadius.circular(borderRadiusKnob.toDouble()),
showBorder: showBorderKnob,
buttonSize: buttonSizesKnob,
isFullWidth: setFullWidthKnob,
Expand All @@ -117,7 +117,7 @@ class ButtonStory extends Story {
const SizedBox(height: 32),
MoonButton.icon(
onTap: showDisabledKnob ? null : () {},
borderRadius: BorderRadius.circular(showBorderRadiusKnob.toDouble()),
borderRadius: BorderRadius.circular(borderRadiusKnob.toDouble()),
showBorder: showBorderKnob,
buttonSize: buttonSizesKnob,
isFullWidth: setFullWidthKnob,
Expand Down
5 changes: 4 additions & 1 deletion example/lib/src/storybook/storybook.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:example/src/storybook/common/widgets/version.dart';
import 'package:example/src/storybook/stories/avatar.dart';
import 'package:example/src/storybook/stories/button.dart';
import 'package:flutter/material.dart';

Expand All @@ -23,7 +24,7 @@ class StorybookPage extends StatelessWidget {
return Stack(
children: [
Storybook(
initialStory: "Buttons",
initialStory: "Avatar",
plugins: _plugins,
wrapperBuilder: (context, child) => MaterialApp(
theme: ThemeData.light().copyWith(extensions: <ThemeExtension<dynamic>>[MoonTheme.light]),
Expand All @@ -43,6 +44,7 @@ class StorybookPage extends StatelessWidget {
child: Scaffold(
extendBody: true,
extendBodyBehindAppBar: true,
backgroundColor: context.moonColors!.beerus,
body: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: child,
Expand All @@ -54,6 +56,7 @@ class StorybookPage extends StatelessWidget {
),
),
stories: [
AvatarStory(),
ButtonStory(),
],
),
Expand Down
2 changes: 2 additions & 0 deletions example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,5 @@ dev_dependencies:
storybook_flutter: ^0.12.0
flutter:
uses-material-design: true
assets:
- assets/images/
1 change: 1 addition & 0 deletions lib/moon_design.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export 'package:moon_design/src/utils/measure_size.dart';
export 'package:moon_design/src/utils/moon_icon.dart';
export 'package:moon_design/src/utils/placeholder_icon.dart';
export 'package:moon_design/src/utils/widget_surveyor.dart';
export 'package:moon_design/src/widgets/avatar/avatar.dart';
export 'package:moon_design/src/widgets/base_control.dart';
export 'package:moon_design/src/widgets/buttons/button.dart';
export 'package:moon_design/src/widgets/buttons/ghost_button.dart';
Expand Down
127 changes: 127 additions & 0 deletions lib/src/theme/avatar_sizes.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import 'dart:ui';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

import 'package:moon_design/src/theme/borders.dart';
import 'package:moon_design/src/theme/sizes.dart';
import 'package:moon_design/src/theme/text_styles.dart';

@immutable
class MoonAvatarSizes extends ThemeExtension<MoonAvatarSizes> with DiagnosticableTreeMixin {
static final _badgeToAvatarRatio = MoonSizes.sizes.x3s / MoonSizes.sizes.x2l;
static final _badgeMarginValueToAvatarRatio = MoonSizes.sizes.x5s / MoonSizes.sizes.x2l;

static final xs = MoonAvatarSizes(
avatarSizeValue: MoonSizes.sizes.xs,
badgeSizeValue: MoonSizes.sizes.xs * _badgeToAvatarRatio,
badgeMarginValue: MoonSizes.sizes.xs * _badgeMarginValueToAvatarRatio,
borderRadius: MoonBorders.borders.interactiveXs,
textStyle: MoonTextStyles.heading.text10,
);

static final sm = MoonAvatarSizes(
avatarSizeValue: MoonSizes.sizes.sm,
badgeSizeValue: MoonSizes.sizes.sm * _badgeToAvatarRatio,
badgeMarginValue: MoonSizes.sizes.sm * _badgeMarginValueToAvatarRatio,
borderRadius: MoonBorders.borders.interactiveSm,
textStyle: MoonTextStyles.heading.text12,
);

static final md = MoonAvatarSizes(
avatarSizeValue: MoonSizes.sizes.md,
badgeSizeValue: MoonSizes.sizes.md * _badgeToAvatarRatio,
badgeMarginValue: MoonSizes.sizes.md * _badgeMarginValueToAvatarRatio,
borderRadius: MoonBorders.borders.interactiveSm,
textStyle: MoonTextStyles.heading.text14,
);

static final lg = MoonAvatarSizes(
avatarSizeValue: MoonSizes.sizes.lg,
badgeSizeValue: MoonSizes.sizes.lg * _badgeToAvatarRatio,
badgeMarginValue: MoonSizes.sizes.lg * _badgeMarginValueToAvatarRatio,
borderRadius: MoonBorders.borders.interactiveSm,
textStyle: MoonTextStyles.heading.text16,
);

static final xl = MoonAvatarSizes(
avatarSizeValue: MoonSizes.sizes.xl,
badgeSizeValue: MoonSizes.sizes.xl * _badgeToAvatarRatio,
badgeMarginValue: MoonSizes.sizes.xl * _badgeMarginValueToAvatarRatio,
borderRadius: MoonBorders.borders.interactiveMd,
textStyle: MoonTextStyles.heading.text16,
);

static final x2l = MoonAvatarSizes(
avatarSizeValue: MoonSizes.sizes.x2l,
badgeSizeValue: MoonSizes.sizes.x2l * _badgeToAvatarRatio,
badgeMarginValue: MoonSizes.sizes.x2l * _badgeMarginValueToAvatarRatio,
borderRadius: MoonBorders.borders.interactiveMd,
textStyle: MoonTextStyles.heading.text20,
);

/// Avatar size value.
final double avatarSizeValue;

/// Avatar size value.
final double badgeSizeValue;

/// Avatar size value.
final double badgeMarginValue;

/// Avatar border radius.
final BorderRadius borderRadius;

/// Avatar text style.
final TextStyle textStyle;

const MoonAvatarSizes({
required this.avatarSizeValue,
required this.badgeSizeValue,
required this.badgeMarginValue,
required this.borderRadius,
required this.textStyle,
});

@override
MoonAvatarSizes copyWith({
double? avatarSizeValue,
double? badgeSizeValue,
double? badgeMarginValue,
BorderRadius? borderRadius,
TextStyle? textStyle,
}) {
return MoonAvatarSizes(
avatarSizeValue: avatarSizeValue ?? this.avatarSizeValue,
badgeSizeValue: badgeSizeValue ?? this.badgeSizeValue,
badgeMarginValue: badgeMarginValue ?? this.badgeMarginValue,
borderRadius: borderRadius ?? this.borderRadius,
textStyle: textStyle ?? this.textStyle,
);
}

@override
MoonAvatarSizes lerp(ThemeExtension<MoonAvatarSizes>? other, double t) {
if (other is! MoonAvatarSizes) return this;

return MoonAvatarSizes(
avatarSizeValue: lerpDouble(avatarSizeValue, other.avatarSizeValue, t)!,
badgeSizeValue: lerpDouble(badgeSizeValue, other.badgeSizeValue, t)!,
badgeMarginValue: lerpDouble(badgeMarginValue, other.badgeMarginValue, t)!,
borderRadius: BorderRadius.lerp(borderRadius, other.borderRadius, t)!,
textStyle: TextStyle.lerp(textStyle, other.textStyle, t)!,
);
}

@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties
..add(DiagnosticsProperty("type", "MoonAvatarSizes"))
..add(DoubleProperty("avatarSizeValue", avatarSizeValue))
..add(DoubleProperty("badgeSizeValue", badgeSizeValue))
..add(DoubleProperty("badgeMarginValue", badgeMarginValue))
..add(DiagnosticsProperty<BorderRadius>("borderRadius", borderRadius))
..add(DiagnosticsProperty<TextStyle>("textStyle", textStyle));
}
}
Loading

0 comments on commit 57d0a0d

Please sign in to comment.