import 'package:flutter/material.dart'; /// A centered empty state display with icon, title, and optional subtitle/action. /// Features a tinted icon circle, fade+slide entrance animation, and clear /// typography hierarchy using the MeshCore design system. class EmptyState extends StatefulWidget { final IconData icon; final String title; final String? subtitle; final Widget? action; const EmptyState({ super.key, required this.icon, required this.title, this.subtitle, this.action, }); @override State createState() => _EmptyStateState(); } class _EmptyStateState extends State with SingleTickerProviderStateMixin { late final AnimationController _controller = AnimationController( vsync: this, duration: const Duration(milliseconds: 420), ); late final CurvedAnimation _curve = CurvedAnimation( parent: _controller, curve: Curves.easeOutCubic, ); @override void initState() { super.initState(); _controller.forward(); } @override void dispose() { _curve.dispose(); _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final scheme = Theme.of(context).colorScheme; return FadeTransition( opacity: _curve, child: SlideTransition( position: Tween( begin: const Offset(0, 0.06), end: Offset.zero, ).animate(_curve), child: Center( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 40), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( width: 80, height: 80, decoration: BoxDecoration( shape: BoxShape.circle, color: scheme.primary.withValues(alpha: 0.08), border: Border.all( color: scheme.primary.withValues(alpha: 0.18), width: 1.5, ), ), child: Icon( widget.icon, size: 36, color: scheme.onSurfaceVariant, ), ), const SizedBox(height: 20), Text( widget.title, style: Theme.of(context).textTheme.titleMedium?.copyWith( fontWeight: FontWeight.w600, color: scheme.onSurface, letterSpacing: -0.1, ), textAlign: TextAlign.center, ), if (widget.subtitle != null) ...[ const SizedBox(height: 8), Text( widget.subtitle!, style: TextStyle( fontSize: 13.5, color: scheme.onSurfaceVariant, height: 1.45, ), textAlign: TextAlign.center, ), ], if (widget.action != null) ...[ const SizedBox(height: 28), widget.action!, ], ], ), ), ), ), ); } }