Skip to content
This repository has been archived by the owner on Jan 9, 2024. It is now read-only.

fix: cta style #39

Merged
merged 9 commits into from
Nov 30, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
4 changes: 3 additions & 1 deletion lib/home/widgets/results_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -588,7 +588,9 @@ class _SeeSourceAnswersButtonState extends State<SeeSourceAnswersButton>
height: 64,
child: TertiaryCTA(
label: l10n.seeSourceAnswers,
icon: vertexIcons.arrowForward.image(),
icon: vertexIcons.arrowForward.image(
color: VertexColors.white,
),
onPressed: () =>
context.read<HomeBloc>().add(const SeeSourceAnswersRequested()),
),
Expand Down
4 changes: 3 additions & 1 deletion lib/home/widgets/welcome_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@ class _WelcomeView extends StatelessWidget {
),
const SizedBox(height: 40),
PrimaryCTA(
icon: vertexIcons.arrowForward.image(),
icon: vertexIcons.arrowForward.image(
color: VertexColors.googleBlue,
),
label: l10n.startAsking,
onPressed: () =>
context.read<HomeBloc>().add(const FromWelcomeToQuestion()),
Expand Down
Binary file modified packages/app_ui/assets/icons/arrow_back.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified packages/app_ui/assets/icons/arrow_forward.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 21 additions & 0 deletions packages/app_ui/lib/src/theme/vertex_theme.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ class VertexTheme {
textTheme: _textTheme,
inputDecorationTheme: _inputDecorationTheme,
useMaterial3: true,
elevatedButtonTheme: _elevatedButtonTheme,
textButtonTheme: _textButtonTheme,
);
}

Expand Down Expand Up @@ -55,4 +57,23 @@ class VertexTheme {
contentPadding: const EdgeInsets.symmetric(vertical: 32),
);
}

static ElevatedButtonThemeData get _elevatedButtonTheme {
return ElevatedButtonThemeData(
style: ElevatedButton.styleFrom(
textStyle: _textTheme.bodyMedium,
backgroundColor: VertexColors.googleBlue,
foregroundColor: VertexColors.white,
),
);
}

static TextButtonThemeData get _textButtonTheme {
return TextButtonThemeData(
style: TextButton.styleFrom(
textStyle: _textTheme.bodyMedium,
foregroundColor: VertexColors.white,
),
);
}
}
35 changes: 16 additions & 19 deletions packages/app_ui/lib/src/widgets/primary_cta.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ class PrimaryCTA extends StatelessWidget {
super.key,
});

/// The image that will be displayed on the left side of the button.
final Image? icon;
/// The widget that will be displayed on the left side of the button.
final Widget? icon;

/// The text that will be displayed on the right side of the button.
final String label;
Expand All @@ -27,31 +27,28 @@ class PrimaryCTA extends StatelessWidget {
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: onPressed,
style: ButtonStyle(
backgroundColor: const MaterialStatePropertyAll(
VertexColors.googleBlue,
),
padding: MaterialStatePropertyAll(
EdgeInsets.only(
left: icon != null ? 24 : 32,
top: 20,
bottom: 20,
right: 32,
),
style: ElevatedButton.styleFrom(
padding: EdgeInsets.only(
left: icon != null ? 8 : 32,
top: 20,
bottom: 20,
right: 32,
),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
if (icon != null) icon!,
if (icon != null)
Padding(
padding: const EdgeInsets.only(right: 16),
child: CircleAvatar(
backgroundColor: VertexColors.white,
child: SizedBox.square(dimension: 24, child: icon),
),
),
Text(
label,
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.w500,
color: VertexColors.white,
),
),
],
),
Expand Down
65 changes: 51 additions & 14 deletions packages/app_ui/lib/src/widgets/tertiary_cta.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ import 'package:flutter/material.dart';

/// {@template tertiary_cta}
/// TertiaryCTA
/// side.
/// {@endtemplate}
class TertiaryCTA extends StatelessWidget {
class TertiaryCTA extends StatefulWidget {
/// {@macro tertiary_cta}
const TertiaryCTA({
required this.label,
Expand All @@ -14,31 +13,69 @@ class TertiaryCTA extends StatelessWidget {
super.key,
});

/// The image that will be displayed on the left side of the button.
final Image? icon;
/// The icon that will be displayed on the left side of the button.
final Widget? icon;

/// The text that will be displayed on the right side of the button.
final String label;

/// The callback that will be called when the button is tapped.
final VoidCallback? onPressed;

@override
State<TertiaryCTA> createState() => _TertiaryCTAState();
}

class _TertiaryCTAState extends State<TertiaryCTA>
with SingleTickerProviderStateMixin {
final DecorationTween decorationTween = DecorationTween(
begin: const BoxDecoration(),
end: const BoxDecoration(
border: Border(
bottom: BorderSide(color: VertexColors.white, width: 2),
),
),
);

late final AnimationController _controller = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 300),
);

@override
Widget build(BuildContext context) {
return TextButton(
onPressed: onPressed,
onPressed: widget.onPressed,
style: const ButtonStyle(
overlayColor: MaterialStatePropertyAll(Colors.transparent),
),
onHover: (hovered) {
if (hovered) {
_controller.forward(from: 0);
} else {
_controller.reverse(from: 1);
}
},
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
if (icon != null) icon!,
Expanded(
child: Text(
label,
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.w500,
color: VertexColors.white,
if (widget.icon != null)
Padding(
padding: const EdgeInsets.only(right: 4),
child: SizedBox.square(
dimension: 24,
child: widget.icon,
),
),
Flexible(
child: DecoratedBoxTransition(
decoration: decorationTween.animate(_controller),
child: Padding(
padding: const EdgeInsets.only(bottom: 4),
child: Text(
widget.label,
textAlign: TextAlign.center,
),
),
),
),
Expand Down
29 changes: 29 additions & 0 deletions packages/app_ui/test/src/widgets/tertiary_cta_test.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import 'package:app_ui/app_ui.dart';
import 'package:app_ui/src/generated/assets.gen.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';

import '../helpers/helpers.dart';
Expand Down Expand Up @@ -33,5 +35,32 @@ void main() {
await tester.tap(find.byType(TertiaryCTA));
expect(called, isTrue);
});

testWidgets('animates on hover', (tester) async {
await tester.pumpApp(
TertiaryCTA(
icon: Assets.icons.arrowForward.image(),
label: 'label',
onPressed: () {},
),
);
var status = AnimationStatus.dismissed;
final widget = tester
.widget<DecoratedBoxTransition>(find.byType(DecoratedBoxTransition));
widget.decoration.addStatusListener((newstatus) {
status = newstatus;
});
final center = tester.getCenter(find.byType(TertiaryCTA));
final gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
await gesture.addPointer();
await gesture.moveTo(center);
expect(status, AnimationStatus.forward);
await tester.pumpAndSettle();
expect(status, AnimationStatus.completed);
await gesture.moveTo(Offset(1000, 1000));
expect(status, AnimationStatus.reverse);
await tester.pumpAndSettle();
expect(status, AnimationStatus.dismissed);
});
});
}