Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: [MDS-592] Create Dropdown component #256

Merged
merged 10 commits into from
Sep 22, 2023
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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