Skip to content

Commit

Permalink
feat: Lenra-192 LenraToggle (#3)
Browse files Browse the repository at this point in the history
* LenraToggle added
Co-authored-by: Louis G <louis@lenra.me>
  • Loading branch information
pichoemr authored Aug 31, 2021
1 parent 6368a87 commit 99a4d6c
Show file tree
Hide file tree
Showing 4 changed files with 256 additions and 64 deletions.
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"dart.lineLength": 120
}
148 changes: 148 additions & 0 deletions lib/component/lenra_toggle.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import 'package:flutter/material.dart';
import 'package:lenra_components/lenra_components.dart';
import 'package:lenra_components/theme/lenra_color_theme_data.dart';

//TODO: move this value in Theme
const double THUMB_RADIUS_RATIO = 3;
const double TRACK_WIDTH_RATIO = 5;
const double TRACK_HEIGHT_RATIO = 3;
const double THUMB_PADDING_RATIO = 0.25;

class LenraToggle extends StatefulWidget {
final bool value;
final Function() onPressed;
final Color activeColor = LenraColorThemeData.LENRA_FUN_GREEN_BASE;
final Color inactiveColor = LenraColorThemeData.GREY_NATURE;
final Color disabledColor = LenraColorThemeData.GREY_LIGHT;
final String? label;
final Color labelColor = LenraColorThemeData.BLACK_MOON;
final Color disabledLabelColor = LenraColorThemeData.GREY_NATURE;
final bool disabled;

const LenraToggle({
required this.value,
required this.onPressed,
this.label,
this.disabled = false,
Key? key,
}) : super(key: key);

@override
_LenraToggleState createState() => _LenraToggleState();
}

class _LenraToggleState extends State<LenraToggle> with SingleTickerProviderStateMixin {
late AnimationController _animationController;
late CurvedAnimation animation;

@override
void initState() {
super.initState();
_animationController = AnimationController(vsync: this, duration: Duration(milliseconds: 150));
animation = CurvedAnimation(
parent: _animationController,
curve: Curves.easeIn,
reverseCurve: Curves.easeOut,
);
}

@override
void didUpdateWidget(LenraToggle oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.value != widget.value) {
if (widget.value) {
_animationController.reverse();
} else {
_animationController.forward();
}
}
}

@override
Widget build(BuildContext context) {
return widget.disabled ? _buildWidget() : _buildInteractiveWidget();
}

Widget _buildInteractiveWidget() {
return MouseRegion(
cursor: SystemMouseCursors.click,
child: GestureDetector(
onTap: widget.onPressed,
child: _buildWidget(),
),
);
}

Widget _buildWidget() {
var lenraSwitch = _LenraSwitch(animation: animation, toggle: widget);
if (widget.label == null) return lenraSwitch;
return LenraRow(
children: [
_buildLabel(),
lenraSwitch,
],
);
}

Widget _buildLabel() {
return Text(
widget.label!,
style: TextStyle(
color: widget.disabled ? widget.disabledLabelColor : widget.labelColor,
fontWeight: FontWeight.w400,
fontSize: 15.0,
),
);
}
}

class _LenraSwitch extends AnimatedWidget {
final LenraToggle toggle;
final Animation<double> animation;

const _LenraSwitch({
Key? key,
required this.animation,
required this.toggle,
}) : super(key: key, listenable: animation);

@override
Widget build(BuildContext context) {
final LenraThemeData finalLenraThemeData = LenraTheme.of(context);

final int thumbPadding = (finalLenraThemeData.baseSize * THUMB_PADDING_RATIO).toInt();
final double thumbRadius = (finalLenraThemeData.baseSize * THUMB_RADIUS_RATIO) - thumbPadding * 2;
final double trackWidth = finalLenraThemeData.baseSize * TRACK_WIDTH_RATIO;
final double trackHeight = finalLenraThemeData.baseSize * TRACK_HEIGHT_RATIO;
final ColorTween colorTween = ColorTween(begin: toggle.inactiveColor, end: toggle.activeColor);
final AlignmentTween alignTween = AlignmentTween(begin: Alignment.centerLeft, end: Alignment.centerRight);

return Container(
width: trackWidth,
height: trackHeight,
padding: EdgeInsets.only(left: thumbPadding.toDouble(), right: thumbPadding.toDouble()),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(trackHeight / 2),
color: toggle.disabled ? toggle.disabledColor : colorTween.evaluate(this.animation)),
child: Align(
alignment: alignTween.evaluate(animation),
child: Container(
width: thumbRadius,
height: thumbRadius,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: LenraColorThemeData.LENRA_WHITE,
boxShadow: [
BoxShadow(
offset: Offset(0, 2.0),
blurRadius: 4.0,
color: Colors.black.withOpacity(0.16),
spreadRadius: 0,
)
],
),
),
),
);
}
}
102 changes: 38 additions & 64 deletions lib/theme/lenra_color_theme_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ class LenraColorThemeData {
static const LENRA_CUSTOM_YELLOW = Color(0xFFF6C28B);
static const LENRA_CUSTOM_GREEN = Color(0xFF57C0B3);

static const GREY_SUPER_LIGHT = Color(0xFFF0F2F5);
static const GREY_LIGHT = Color(0xFFDCE0E7);
static const GREY_NATURE = Color(0xFFA9B2C4);
static const GREY_DARK_GREY = Color(0xFFF7A8598);
static const BLACK_MOON = Color(0xFF1E232C);

static const LENRA_FUN_RED_PULSE = Color(0xFFE92236);
static const LENRA_FUN_RED_BASE = Color(0xFFF27A86);
static const LENRA_FUN_RED_FADE = Color(0xFFFACACF);
Expand Down Expand Up @@ -71,39 +77,25 @@ class LenraColorThemeData {
Color? tertiaryForegroundDisabledColor,
}) {
this.primaryBackgroundColor = primaryBackgroundColor ?? LENRA_BLUE;
this.primaryBackgroundHoverColor =
primaryBackgroundHoverColor ?? LENRA_BLUE_HOVER;
this.primaryBackgroundDisabledColor =
primaryBackgroundDisabledColor ?? LENRA_BLUE_UNAVAILABLE;
this.primaryBackgroundHoverColor = primaryBackgroundHoverColor ?? LENRA_BLUE_HOVER;
this.primaryBackgroundDisabledColor = primaryBackgroundDisabledColor ?? LENRA_BLUE_UNAVAILABLE;
this.primaryForegroundColor = primaryForegroundColor ?? LENRA_WHITE;
this.primaryForegroundHoverColor =
primaryForegroundHoverColor ?? LENRA_WHITE;
this.primaryForegroundDisabledColor =
primaryForegroundDisabledColor ?? LENRA_WHITE;
this.primaryForegroundHoverColor = primaryForegroundHoverColor ?? LENRA_WHITE;
this.primaryForegroundDisabledColor = primaryForegroundDisabledColor ?? LENRA_WHITE;

this.secondaryBackgroundColor =
secondaryBackgroundColor ?? Colors.transparent;
this.secondaryBackgroundHoverColor =
secondaryBackgroundHoverColor ?? LENRA_BLUE_UNAVAILABLE;
this.secondaryBackgroundDisabledColor =
secondaryBackgroundDisabledColor ?? Colors.transparent;
this.secondaryBackgroundColor = secondaryBackgroundColor ?? Colors.transparent;
this.secondaryBackgroundHoverColor = secondaryBackgroundHoverColor ?? LENRA_BLUE_UNAVAILABLE;
this.secondaryBackgroundDisabledColor = secondaryBackgroundDisabledColor ?? Colors.transparent;
this.secondaryForegroundColor = secondaryForegroundColor ?? LENRA_BLUE;
this.secondaryForegroundHoverColor =
secondaryForegroundHoverColor ?? LENRA_BLUE;
this.secondaryForegroundDisabledColor =
secondaryForegroundDisabledColor ?? LENRA_BLUE_UNAVAILABLE;
this.secondaryForegroundHoverColor = secondaryForegroundHoverColor ?? LENRA_BLUE;
this.secondaryForegroundDisabledColor = secondaryForegroundDisabledColor ?? LENRA_BLUE_UNAVAILABLE;

this.tertiaryBackgroundColor =
tertiaryBackgroundColor ?? Colors.transparent;
this.tertiaryBackgroundHoverColor =
tertiaryBackgroundHoverColor ?? LENRA_BLUE_UNAVAILABLE;
this.tertiaryBackgroundDisabledColor =
tertiaryBackgroundDisabledColor ?? Colors.transparent;
this.tertiaryBackgroundColor = tertiaryBackgroundColor ?? Colors.transparent;
this.tertiaryBackgroundHoverColor = tertiaryBackgroundHoverColor ?? LENRA_BLUE_UNAVAILABLE;
this.tertiaryBackgroundDisabledColor = tertiaryBackgroundDisabledColor ?? Colors.transparent;
this.tertiaryForegroundColor = tertiaryForegroundColor ?? LENRA_BLUE;
this.tertiaryForegroundHoverColor =
tertiaryForegroundHoverColor ?? LENRA_BLUE;
this.tertiaryForegroundDisabledColor =
tertiaryForegroundDisabledColor ?? LENRA_BLUE_UNAVAILABLE;
this.tertiaryForegroundHoverColor = tertiaryForegroundHoverColor ?? LENRA_BLUE;
this.tertiaryForegroundDisabledColor = tertiaryForegroundDisabledColor ?? LENRA_BLUE_UNAVAILABLE;
}

copyWith({
Expand All @@ -127,42 +119,24 @@ class LenraColorThemeData {
Color? tertiaryForegroundDisabledColor,
}) {
return LenraColorThemeData(
primaryBackgroundColor:
primaryBackgroundColor ?? this.primaryBackgroundColor,
primaryBackgroundHoverColor:
primaryBackgroundHoverColor ?? this.primaryBackgroundHoverColor,
primaryBackgroundDisabledColor:
primaryBackgroundDisabledColor ?? this.primaryBackgroundDisabledColor,
primaryForegroundColor:
primaryForegroundColor ?? this.primaryForegroundColor,
primaryForegroundHoverColor:
primaryForegroundHoverColor ?? this.primaryForegroundColor,
primaryForegroundDisabledColor:
primaryForegroundDisabledColor ?? this.primaryForegroundDisabledColor,
secondaryBackgroundColor:
secondaryBackgroundColor ?? this.secondaryBackgroundColor,
secondaryBackgroundHoverColor:
secondaryBackgroundHoverColor ?? this.secondaryBackgroundHoverColor,
secondaryBackgroundDisabledColor: secondaryBackgroundDisabledColor ??
this.secondaryBackgroundDisabledColor,
secondaryForegroundColor:
secondaryForegroundColor ?? this.secondaryForegroundColor,
secondaryForegroundHoverColor:
secondaryForegroundHoverColor ?? this.secondaryForegroundHoverColor,
secondaryForegroundDisabledColor: secondaryForegroundDisabledColor ??
this.secondaryForegroundDisabledColor,
tertiaryBackgroundColor:
tertiaryBackgroundColor ?? this.tertiaryBackgroundColor,
tertiaryBackgroundHoverColor:
tertiaryBackgroundHoverColor ?? this.tertiaryBackgroundHoverColor,
tertiaryBackgroundDisabledColor: tertiaryBackgroundDisabledColor ??
this.tertiaryBackgroundDisabledColor,
tertiaryForegroundColor:
tertiaryForegroundColor ?? this.tertiaryForegroundColor,
tertiaryForegroundHoverColor:
tertiaryForegroundHoverColor ?? this.tertiaryForegroundHoverColor,
tertiaryForegroundDisabledColor: tertiaryForegroundDisabledColor ??
this.tertiaryForegroundDisabledColor,
primaryBackgroundColor: primaryBackgroundColor ?? this.primaryBackgroundColor,
primaryBackgroundHoverColor: primaryBackgroundHoverColor ?? this.primaryBackgroundHoverColor,
primaryBackgroundDisabledColor: primaryBackgroundDisabledColor ?? this.primaryBackgroundDisabledColor,
primaryForegroundColor: primaryForegroundColor ?? this.primaryForegroundColor,
primaryForegroundHoverColor: primaryForegroundHoverColor ?? this.primaryForegroundColor,
primaryForegroundDisabledColor: primaryForegroundDisabledColor ?? this.primaryForegroundDisabledColor,
secondaryBackgroundColor: secondaryBackgroundColor ?? this.secondaryBackgroundColor,
secondaryBackgroundHoverColor: secondaryBackgroundHoverColor ?? this.secondaryBackgroundHoverColor,
secondaryBackgroundDisabledColor: secondaryBackgroundDisabledColor ?? this.secondaryBackgroundDisabledColor,
secondaryForegroundColor: secondaryForegroundColor ?? this.secondaryForegroundColor,
secondaryForegroundHoverColor: secondaryForegroundHoverColor ?? this.secondaryForegroundHoverColor,
secondaryForegroundDisabledColor: secondaryForegroundDisabledColor ?? this.secondaryForegroundDisabledColor,
tertiaryBackgroundColor: tertiaryBackgroundColor ?? this.tertiaryBackgroundColor,
tertiaryBackgroundHoverColor: tertiaryBackgroundHoverColor ?? this.tertiaryBackgroundHoverColor,
tertiaryBackgroundDisabledColor: tertiaryBackgroundDisabledColor ?? this.tertiaryBackgroundDisabledColor,
tertiaryForegroundColor: tertiaryForegroundColor ?? this.tertiaryForegroundColor,
tertiaryForegroundHoverColor: tertiaryForegroundHoverColor ?? this.tertiaryForegroundHoverColor,
tertiaryForegroundDisabledColor: tertiaryForegroundDisabledColor ?? this.tertiaryForegroundDisabledColor,
);
}
}
67 changes: 67 additions & 0 deletions test/component/lenra_toggle_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:lenra_components/lenra_components.dart';
import '../../lib/component/lenra_toggle.dart';

import '../utils/lenra_page_test_help.dart';

void main() {
test('LenraToggle test', () {
LenraToggle component = LenraToggle(value: true, onPressed: () {});
expect(component is LenraToggle, true);
});

testWidgets('LenraToggle without label', (WidgetTester tester) async {
await tester.pumpWidget(createComponentTestWidgets(
LenraToggle(
value: true,
onPressed: () {},
),
));

expect((tester.widget(find.byType(LenraToggle))) is LenraToggle, true);
expect((find.byType(Text)), findsNothing);
});
testWidgets('LenraToggle with label', (WidgetTester tester) async {
await tester.pumpWidget(createComponentTestWidgets(
LenraToggle(
value: true,
onPressed: () {},
label: "test",
),
));

expect((tester.widget(find.byType(LenraRow)) as LenraRow).children.first is Text, true);
});
testWidgets('LenraToggle size', (WidgetTester tester) async {
await tester.pumpWidget(createComponentTestWidgets(
LenraToggle(
value: true,
onPressed: () {},
),
));

expect((tester.getSize(find.byType(LenraToggle)).width), equals(40));
expect((tester.getSize(find.byType(LenraToggle)).height), equals(24));
});

testWidgets('LenraToggle tap should change the state', (WidgetTester tester) async {
bool value = false;
await tester.pumpWidget(createComponentTestWidgets(
LenraToggle(
value: value,
onPressed: () {
value = !value;
},
),
));
expect(value, false);

await tester.tap(find.byType(LenraToggle));
await tester.pumpAndSettle();

expect(value, true);
});
}

0 comments on commit 99a4d6c

Please sign in to comment.