import 'package:flutter/material.dart'; import '../../../core/theme/design_tokens.dart'; import 'toast_type.dart'; import 'toast_type_config.dart'; class Toast { static void show( BuildContext context, String message, { ToastType type = ToastType.info, Duration duration = const Duration(seconds: 2), }) { final overlay = Overlay.of(context); late OverlayEntry entry; entry = OverlayEntry( builder: (context) => _ToastWidget( message: message, type: type, duration: duration, onDismiss: () => entry.remove(), ), ); overlay.insert(entry); } } class _ToastWidget extends StatefulWidget { final String message; final ToastType type; final Duration duration; final VoidCallback onDismiss; const _ToastWidget({ required this.message, required this.type, required this.duration, required this.onDismiss, }); @override State<_ToastWidget> createState() => _ToastWidgetState(); } class _ToastWidgetState extends State<_ToastWidget> with SingleTickerProviderStateMixin { late AnimationController _controller; late Animation _slideAnimation; late Animation _fadeAnimation; @override void initState() { super.initState(); _controller = AnimationController( duration: const Duration(milliseconds: 250), vsync: this, ); _slideAnimation = Tween( begin: const Offset(0, -1), end: Offset.zero, ).animate(CurvedAnimation(parent: _controller, curve: Curves.easeOut)); _fadeAnimation = Tween(begin: 0, end: 1).animate(_controller); _controller.forward(); Future.delayed(widget.duration, _dismiss); } void _dismiss() { if (!mounted) return; _controller.reverse().then((_) => widget.onDismiss()); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final config = ToastTypeConfig.fromType(widget.type); return Positioned( top: MediaQuery.of(context).padding.top + 16, left: 16, right: 16, child: SlideTransition( position: _slideAnimation, child: FadeTransition( opacity: _fadeAnimation, child: Material( color: Colors.transparent, child: Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), decoration: BoxDecoration( color: config.backgroundColor, borderRadius: BorderRadius.circular(AppRadius.md), boxShadow: [ BoxShadow( color: Colors.black.withValues(alpha: 0.1), blurRadius: 8, offset: const Offset(0, 2), ), ], ), child: Row( children: [ Icon(config.icon, size: 20, color: config.iconColor), const SizedBox(width: 12), Expanded( child: Text( widget.message, style: TextStyle(fontSize: 14, color: config.textColor), ), ), ], ), ), ), ), ), ); } }