import 'package:flutter/material.dart'; enum SnackBarType { success, error, warning, info, } class AppSnackBar { static void show({ required BuildContext context, required String message, SnackBarType type = SnackBarType.info, Duration duration = const Duration(seconds: 3), String? actionLabel, VoidCallback? onActionPressed, }) { // Remove any existing snackbars ScaffoldMessenger.of(context).hideCurrentSnackBar(); final snackBar = SnackBar( content: _SnackBarContent( message: message, type: type, ), backgroundColor: Colors.transparent, elevation: 0, duration: duration, behavior: SnackBarBehavior.floating, margin: const EdgeInsets.all(16), padding: EdgeInsets.zero, action: actionLabel != null ? SnackBarAction( label: actionLabel, textColor: _getActionColor(type), onPressed: onActionPressed ?? () {}, ) : null, ); ScaffoldMessenger.of(context).showSnackBar(snackBar); } static void showSuccess({ required BuildContext context, required String message, Duration duration = const Duration(seconds: 3), String? actionLabel, VoidCallback? onActionPressed, }) { show( context: context, message: message, type: SnackBarType.success, duration: duration, actionLabel: actionLabel, onActionPressed: onActionPressed, ); } static void showError({ required BuildContext context, required String message, Duration duration = const Duration(seconds: 4), String? actionLabel, VoidCallback? onActionPressed, }) { show( context: context, message: message, type: SnackBarType.error, duration: duration, actionLabel: actionLabel, onActionPressed: onActionPressed, ); } static void showWarning({ required BuildContext context, required String message, Duration duration = const Duration(seconds: 3), String? actionLabel, VoidCallback? onActionPressed, }) { show( context: context, message: message, type: SnackBarType.warning, duration: duration, actionLabel: actionLabel, onActionPressed: onActionPressed, ); } static void showInfo({ required BuildContext context, required String message, Duration duration = const Duration(seconds: 3), String? actionLabel, VoidCallback? onActionPressed, }) { show( context: context, message: message, type: SnackBarType.info, duration: duration, actionLabel: actionLabel, onActionPressed: onActionPressed, ); } static Color _getActionColor(SnackBarType type) { switch (type) { case SnackBarType.success: return Colors.green.shade100; case SnackBarType.error: return Colors.red.shade100; case SnackBarType.warning: return Colors.orange.shade100; case SnackBarType.info: return Colors.blue.shade100; } } } class _SnackBarContent extends StatelessWidget { final String message; final SnackBarType type; const _SnackBarContent({ required this.message, required this.type, }); @override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), decoration: BoxDecoration( color: _getBackgroundColor(), borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 8, offset: const Offset(0, 2), ), ], border: Border.all( color: _getBorderColor(), width: 1, ), ), child: Row( children: [ Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: _getIconBackgroundColor(), shape: BoxShape.circle, ), child: Icon( _getIcon(), color: _getIconColor(), size: 20, ), ), const SizedBox(width: 12), Expanded( child: Text( message, style: TextStyle( color: _getTextColor(), fontSize: 14, fontWeight: FontWeight.w500, ), ), ), ], ), ); } Color _getBackgroundColor() { switch (type) { case SnackBarType.success: return Colors.green.shade50; case SnackBarType.error: return Colors.red.shade50; case SnackBarType.warning: return Colors.orange.shade50; case SnackBarType.info: return Colors.blue.shade50; } } Color _getBorderColor() { switch (type) { case SnackBarType.success: return Colors.green.shade200; case SnackBarType.error: return Colors.red.shade200; case SnackBarType.warning: return Colors.orange.shade200; case SnackBarType.info: return Colors.blue.shade200; } } Color _getIconBackgroundColor() { switch (type) { case SnackBarType.success: return Colors.green.shade100; case SnackBarType.error: return Colors.red.shade100; case SnackBarType.warning: return Colors.orange.shade100; case SnackBarType.info: return Colors.blue.shade100; } } Color _getIconColor() { switch (type) { case SnackBarType.success: return Colors.green.shade700; case SnackBarType.error: return Colors.red.shade700; case SnackBarType.warning: return Colors.orange.shade700; case SnackBarType.info: return Colors.blue.shade700; } } Color _getTextColor() { switch (type) { case SnackBarType.success: return Colors.green.shade800; case SnackBarType.error: return Colors.red.shade800; case SnackBarType.warning: return Colors.orange.shade800; case SnackBarType.info: return Colors.blue.shade800; } } IconData _getIcon() { switch (type) { case SnackBarType.success: return Icons.check_circle; case SnackBarType.error: return Icons.error; case SnackBarType.warning: return Icons.warning; case SnackBarType.info: return Icons.info; } } }