feat: add haptic feedback to more user interactions
Some checks failed
Pull Request Pipeline / test (pull_request) Successful in 49s
Pull Request Pipeline / lint (pull_request) Failing after 50s

This commit is contained in:
2026-05-11 10:27:35 +02:00
parent 1d20127af4
commit bc59d1d91c
20 changed files with 165 additions and 53 deletions

View File

@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:tallee/core/custom_theme.dart';
import 'package:tallee/core/enums.dart';
@@ -48,7 +49,12 @@ class CustomWidthButton extends StatelessWidget {
)!;
return ElevatedButton(
onPressed: onPressed,
onPressed: onPressed == null
? null
: () async {
await HapticFeedback.selectionClick();
onPressed!.call();
},
style: ElevatedButton.styleFrom(
foregroundColor: textcolor,
disabledForegroundColor: disabledTextColor,
@@ -78,7 +84,12 @@ class CustomWidthButton extends StatelessWidget {
: Color.lerp(CustomTheme.primaryColor, Colors.black, 0.5)!;
return OutlinedButton(
onPressed: onPressed,
onPressed: onPressed == null
? null
: () async {
await HapticFeedback.selectionClick();
onPressed!.call();
},
style: OutlinedButton.styleFrom(
foregroundColor: textcolor,
disabledForegroundColor: disabledTextColor,
@@ -110,7 +121,12 @@ class CustomWidthButton extends StatelessWidget {
disabledBackgroundColor = Colors.transparent;
return TextButton(
onPressed: onPressed,
onPressed: onPressed == null
? null
: () async {
await HapticFeedback.selectionClick();
onPressed!.call();
},
style: TextButton.styleFrom(
foregroundColor: textcolor,
disabledForegroundColor: disabledTextColor,

View File

@@ -1,6 +1,6 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:tallee/presentation/widgets/buttons/haptic_icon_button.dart';
class HapticBackButton extends StatelessWidget {
const HapticBackButton({super.key});
@@ -13,10 +13,9 @@ class HapticBackButton extends StatelessWidget {
_ => Icons.arrow_back_rounded,
};
return IconButton(
return HapticIconButton(
icon: Icon(iconData),
onPressed: () async {
await HapticFeedback.mediumImpact();
Navigator.of(context).maybePop();
},
);

View File

@@ -1,7 +1,7 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:tallee/presentation/widgets/buttons/haptic_icon_button.dart';
class HapticCloseButton extends StatelessWidget {
const HapticCloseButton({super.key});
@@ -13,10 +13,9 @@ class HapticCloseButton extends StatelessWidget {
_ => Icons.close_rounded,
};
return IconButton(
return HapticIconButton(
icon: Icon(iconData),
onPressed: () async {
await HapticFeedback.mediumImpact();
Navigator.of(context).maybePop();
},
);

View File

@@ -0,0 +1,54 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class HapticIconButton extends StatelessWidget {
const HapticIconButton({
super.key,
required this.icon,
required this.onPressed,
this.tooltip,
this.iconSize,
this.color,
this.padding,
this.alignment,
this.constraints,
this.style,
this.isSelected,
this.selectedIcon,
});
final Widget icon;
final VoidCallback? onPressed;
final String? tooltip;
final double? iconSize;
final Color? color;
final EdgeInsetsGeometry? padding;
final AlignmentGeometry? alignment;
final BoxConstraints? constraints;
final ButtonStyle? style;
final bool? isSelected;
final Widget? selectedIcon;
@override
Widget build(BuildContext context) {
return IconButton(
tooltip: tooltip,
iconSize: iconSize,
color: color,
padding: padding,
alignment: alignment ?? Alignment.center,
constraints: constraints,
style: style,
isSelected: isSelected,
selectedIcon: selectedIcon,
icon: icon,
onPressed: onPressed == null
? null
: () async {
await HapticFeedback.selectionClick();
onPressed!.call();
},
);
}
}

View File

@@ -1,6 +1,7 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class MainMenuButton extends StatefulWidget {
/// A button for the main menu with an optional icon and a press animation.
@@ -78,6 +79,7 @@ class _MainMenuButtonState extends State<MainMenuButton>
onTapUp: (_) async {
_cancelTimers();
if (mounted && !_isLongPressing) {
await HapticFeedback.selectionClick();
widget.onPressed();
}
_isLongPressing = false;