Skip to content

Commit

Permalink
feat: [MDS-592] Create Dropdown component (#256)
Browse files Browse the repository at this point in the history
  • Loading branch information
Kypsis committed Sep 22, 2023
1 parent c044791 commit adee0d1
Show file tree
Hide file tree
Showing 13 changed files with 1,209 additions and 40 deletions.
221 changes: 221 additions & 0 deletions example/lib/src/storybook/stories/dropdown.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
import 'package:example/src/storybook/common/color_options.dart';
import 'package:flutter/material.dart';
import 'package:moon_design/moon_design.dart';

import 'package:storybook_flutter/storybook_flutter.dart';

const String _groupId = "dropdown";

bool _show = false;
bool _showInner = false;
Color? _buttonColor;
String _buttonName = "Piccolo";

class DropdownStory extends Story {
DropdownStory()
: super(
name: "Dropdown",
builder: (BuildContext context) {
final dropdownAnchorPositionKnob = context.knobs.nullable.options(
label: "dropdownAnchorPosition",
description: "Anchor position variants for MoonDropdown on the child (target).",
enabled: false,
initial: MoonDropdownAnchorPosition.bottom,
options: const [
Option(label: "top", value: MoonDropdownAnchorPosition.top),
Option(label: "bottom", value: MoonDropdownAnchorPosition.bottom),
Option(label: "left", value: MoonDropdownAnchorPosition.left),
Option(label: "right", value: MoonDropdownAnchorPosition.right),
Option(label: "topLeft", value: MoonDropdownAnchorPosition.topLeft),
Option(label: "topRight", value: MoonDropdownAnchorPosition.topRight),
Option(label: "bottomLeft", value: MoonDropdownAnchorPosition.bottomLeft),
Option(label: "bottomRight", value: MoonDropdownAnchorPosition.bottomRight),
Option(label: "vertical", value: MoonDropdownAnchorPosition.vertical),
Option(label: "horizontal", value: MoonDropdownAnchorPosition.horizontal),
],
);

final backgroundColorKnob = context.knobs.nullable.options(
label: "backgroundColor",
description: "MoonColors variants for MoonDropdown background.",
enabled: false,
initial: 0,
// piccolo
options: colorOptions,
);

final backgroundColor = colorTable(context)[backgroundColorKnob ?? 40];

final borderColorKnob = context.knobs.nullable.options(
label: "borderColor",
description: "MoonColors variants for MoonDropdown border.",
enabled: false,
initial: 0,
// piccolo
options: colorOptions,
);

final borderColor = colorTable(context)[borderColorKnob ?? 40];

final borderRadiusKnob = context.knobs.nullable.sliderInt(
label: "borderRadius",
description: "Border radius for MoonDropdown.",
enabled: false,
initial: 8,
max: 32,
);

final distanceToTargetKnob = context.knobs.nullable.slider(
label: "distanceToTarget",
description: "Set the distance to target child widget.",
enabled: false,
initial: 8,
max: 100,
);

final showShadowKnob = context.knobs.boolean(
label: "Show shadow",
description: "Show shadows under MoonDropdown.",
initial: true,
);

final constrainWidthToChildKnob = context.knobs.boolean(
label: "constrainWidthToChild",
description: "Constrain the width of the MoonDropdown to be same as the child (target).",
initial: true,
);

// Used to avoid the stale closure within callbacks in Story
final colorPiccolo = context.moonColors!.piccolo;
final colorKrillin = context.moonColors!.krillin100;
final colorRoshi100 = context.moonColors!.roshi100;
final colorRoshi60 = context.moonColors!.roshi60;
final colorRoshi10 = context.moonColors!.roshi10;

return Padding(
padding: const EdgeInsets.symmetric(vertical: 64),
child: StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
MoonDropdown(
show: _show,
groupId: _groupId,
maxWidth: 250,
borderColor: borderColor ?? Colors.transparent,
backgroundColor: backgroundColor,
borderRadius:
borderRadiusKnob != null ? BorderRadius.circular(borderRadiusKnob.toDouble()) : null,
constrainWidthToChild: constrainWidthToChildKnob,
distanceToTarget: distanceToTargetKnob,
dropdownAnchorPosition: dropdownAnchorPositionKnob ?? MoonDropdownAnchorPosition.bottom,
dropdownShadows: showShadowKnob == true ? null : [],
onTapOutside: () => setState(() {
_show = false;
_showInner = false;
}),
content: Column(
children: [
MoonMenuItem(
title: const Text("Piccolo"),
borderRadius: const MoonSquircleBorderRadius.all(MoonSquircleRadius(cornerRadius: 12)),
onTap: () => setState(() {
_show = false;
_buttonName = "Piccolo";
_buttonColor = colorPiccolo;
}),
),
const SizedBox(height: 4),
MoonMenuItem(
title: const Text("Krillin"),
borderRadius: const MoonSquircleBorderRadius.all(MoonSquircleRadius(cornerRadius: 12)),
onTap: () => setState(() {
_show = false;
_buttonName = "Krillin";
_buttonColor = colorKrillin;
}),
),
const SizedBox(height: 4),
MoonDropdown(
show: _showInner,
groupId: _groupId,
maxWidth: 100,
constrainWidthToChild: constrainWidthToChildKnob,
distanceToTarget: distanceToTargetKnob,
dropdownAnchorPosition: dropdownAnchorPositionKnob ?? MoonDropdownAnchorPosition.bottom,
followerAnchor: dropdownAnchorPositionKnob == null ? Alignment.topLeft : null,
targetAnchor: dropdownAnchorPositionKnob == null ? Alignment.topRight : null,
offset: dropdownAnchorPositionKnob == null ? const Offset(8, 0) : null,
content: Column(
children: [
MoonMenuItem(
title: const Text("Roshi100"),
borderRadius:
const MoonSquircleBorderRadius.all(MoonSquircleRadius(cornerRadius: 12)),
onTap: () => setState(() {
_show = false;
_showInner = false;
_buttonName = "Roshi100";
_buttonColor = colorRoshi100;
}),
),
const SizedBox(height: 4),
MoonMenuItem(
title: const Text("Roshi60"),
borderRadius:
const MoonSquircleBorderRadius.all(MoonSquircleRadius(cornerRadius: 12)),
onTap: () => setState(() {
_show = false;
_showInner = false;
_buttonName = "Roshi60";
_buttonColor = colorRoshi60;
}),
),
const SizedBox(height: 4),
MoonMenuItem(
title: const Text("Roshi10"),
borderRadius:
const MoonSquircleBorderRadius.all(MoonSquircleRadius(cornerRadius: 12)),
onTap: () => setState(() {
_show = false;
_showInner = false;
_buttonName = "Roshi10";
_buttonColor = colorRoshi10;
}),
),
],
),
child: MoonMenuItem(
backgroundColor: _showInner ? context.moonColors!.heles : null,
title: const Text("Roshi"),
borderRadius:
const MoonSquircleBorderRadius.all(MoonSquircleRadius(cornerRadius: 12)),
onTap: () => setState(() {
_showInner = !_showInner;
}),
trailing: const MoonIcon(
MoonIcons.chevron_right_16,
size: 16,
),
),
),
],
),
child: MoonFilledButton(
width: 128,
label: Text(_buttonName),
backgroundColor: _buttonColor,
onTap: () => setState(() => _show = !_show),
),
),
],
),
);
},
),
);
},
);
}
20 changes: 3 additions & 17 deletions example/lib/src/storybook/stories/popover.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,6 @@ class PopoverStory extends Story {
],
);

final textColorKnob = context.knobs.nullable.options(
label: "Text color",
description: "MoonColors variants for MoonPopover text.",
enabled: false,
initial: 0,
// piccolo
options: colorOptions,
);

final textColor = colorTable(context)[textColorKnob ?? 40];

final backgroundColorKnob = context.knobs.nullable.options(
label: "backgroundColor",
description: "MoonColors variants for MoonPopover background.",
Expand Down Expand Up @@ -106,13 +95,13 @@ class PopoverStory extends Story {
distanceToTarget: distanceToTargetKnob,
popoverPosition: popoverPositionKnob ?? MoonPopoverPosition.top,
popoverShadows: showShadowKnob == true ? null : [],
onTapOutside: () => setState(() => show = false),
content: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 190),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
textDirection: Directionality.of(context),
mainAxisSize: MainAxisSize.min,
children: [
MoonAvatar(
Expand All @@ -121,10 +110,7 @@ class PopoverStory extends Story {
),
const SizedBox(width: 12),
Expanded(
child: Text(
customLabelTextKnob,
style: TextStyle(color: textColor),
),
child: Text(customLabelTextKnob),
),
],
),
Expand All @@ -139,7 +125,7 @@ class PopoverStory extends Story {
),
),
child: MoonFilledButton(
onTap: () => setState(() => show = true),
onTap: () => setState(() => show = !show),
label: const Text("Tap me"),
),
);
Expand Down
2 changes: 2 additions & 0 deletions example/lib/src/storybook/storybook.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import 'package:example/src/storybook/stories/circular_loader.dart';
import 'package:example/src/storybook/stories/circular_progress.dart';
import 'package:example/src/storybook/stories/dot_indicator.dart';
import 'package:example/src/storybook/stories/drawer.dart';
import 'package:example/src/storybook/stories/dropdown.dart';
import 'package:example/src/storybook/stories/icons.dart';
import 'package:example/src/storybook/stories/linear_loader.dart';
import 'package:example/src/storybook/stories/linear_progress.dart';
Expand Down Expand Up @@ -123,6 +124,7 @@ class StorybookPage extends StatelessWidget {
CircularProgressStory(),
DotIndicatorStory(),
DrawerStory(),
DropdownStory(),
IconsStory(),
LinearLoaderStory(),
LinearProgressStory(),
Expand Down
1 change: 1 addition & 0 deletions lib/moon_design.dart
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ export 'package:moon_design/src/widgets/common/progress_indicators/circular_prog
export 'package:moon_design/src/widgets/common/progress_indicators/linear_progress_indicator.dart';
export 'package:moon_design/src/widgets/dot_indicator/dot_indicator.dart';
export 'package:moon_design/src/widgets/drawer/drawer.dart';
export 'package:moon_design/src/widgets/dropdown/dropdown.dart';
export 'package:moon_design/src/widgets/loaders/circular_loader.dart';
export 'package:moon_design/src/widgets/loaders/linear_loader.dart';
export 'package:moon_design/src/widgets/menu_item/menu_item.dart';
Expand Down
56 changes: 56 additions & 0 deletions lib/src/theme/dropdown/dropdown_colors.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

import 'package:moon_design/src/utils/color_premul_lerp.dart';

@immutable
class MoonDropdownColors extends ThemeExtension<MoonDropdownColors> with DiagnosticableTreeMixin {
/// Dropdown text color.
final Color textColor;

/// Dropdown icon color.
final Color iconColor;

/// Dropdown background color.
final Color backgroundColor;

const MoonDropdownColors({
required this.textColor,
required this.iconColor,
required this.backgroundColor,
});

@override
MoonDropdownColors copyWith({
Color? textColor,
Color? iconColor,
Color? backgroundColor,
}) {
return MoonDropdownColors(
textColor: textColor ?? this.textColor,
iconColor: iconColor ?? this.iconColor,
backgroundColor: backgroundColor ?? this.backgroundColor,
);
}

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

return MoonDropdownColors(
textColor: colorPremulLerp(textColor, other.textColor, t)!,
iconColor: colorPremulLerp(iconColor, other.iconColor, t)!,
backgroundColor: colorPremulLerp(backgroundColor, other.backgroundColor, t)!,
);
}

@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties
..add(DiagnosticsProperty("type", "MoonDropdownColors"))
..add(ColorProperty("textColor", textColor))
..add(ColorProperty("iconColor", iconColor))
..add(ColorProperty("backgroundColor", backgroundColor));
}
}
Loading

0 comments on commit adee0d1

Please sign in to comment.