import 'dart:ui'; import 'package:flutter/cupertino.dart'; import 'package:please_pay_me/theme/tokens.dart'; import 'package:please_pay_me/ui/atoms/app_text.dart'; /// iOS has no SnackBar — the platform idiom is a floating blurred capsule /// (AirPods / Silent-mode style). Kept dismiss-free and auto-hiding. class AppToast extends StatelessWidget { const AppToast({ super.key, required this.message, this.icon = CupertinoIcons.check_mark_circled_solid, this.tint = AppColors.accent, }); final String message; final IconData? icon; final Color tint; @override Widget build(BuildContext context) { return ClipRRect( borderRadius: BorderRadius.circular(AppRadii.capsule), child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 20, sigmaY: 20), child: Container( padding: const EdgeInsets.symmetric( horizontal: AppSpacing.s4, vertical: AppSpacing.s3, ), decoration: BoxDecoration( color: AppColors.of(context, AppColors.groupedSurface).withValues(alpha: 0.82), borderRadius: BorderRadius.circular(AppRadii.capsule), boxShadow: const [ BoxShadow(color: Color(0x1F000000), blurRadius: 24, offset: Offset(0, 8)), ], ), child: Row( mainAxisSize: MainAxisSize.min, children: [ if (icon != null) ...[ Icon(icon, size: 20, color: AppColors.of(context, tint)), const SizedBox(width: AppSpacing.s2), ], Flexible(child: AppText.subhead(message, color: AppColors.label)), ], ), ), ), ); } } Future showAppToast( BuildContext context, { required String message, IconData? icon = CupertinoIcons.check_mark_circled_solid, Duration duration = const Duration(seconds: 2), }) async { final overlay = Overlay.of(context, rootOverlay: true); final entry = OverlayEntry( builder: (ctx) => Positioned( left: AppSpacing.s5, right: AppSpacing.s5, bottom: MediaQuery.of(ctx).padding.bottom + AppSpacing.s7, child: SafeArea( top: false, child: Center(child: AppToast(message: message, icon: icon)), ), ), ); overlay.insert(entry); await Future.delayed(duration); entry.remove(); }