/// 空态(UI-01):图标 + 标题 + 说明 + 可选操作按钮,居中布局。 /// /// 用于列表/工作区「暂无内容」的引导(相册为空、队列为空等);标题与 /// 说明由调用方传入(本地化),操作按钮为次强调(tonal,不与页面主 /// CTA 争夺层级)。与 ErrorState 的区别:空态是正常状态,无重试语义。 library; import 'package:flutter/material.dart'; import '../tokens.dart'; /// 空态视图。 class EmptyState extends StatelessWidget { const EmptyState({ required this.icon, required this.title, this.subtitle, this.actionLabel, this.onAction, super.key, }); /// 主题图标(如 [Icons.photo_library_outlined])。 final IconData icon; /// 主文案(如「暂无相册」)。 final String title; /// 补充说明;null 不占位。 final String? subtitle; /// 可选操作按钮文案;null 不显示按钮。 final String? actionLabel; /// 操作回调(与 [actionLabel] 成对提供)。 final VoidCallback? onAction; @override Widget build(BuildContext context) { final theme = Theme.of(context); return Center( child: Padding( padding: const EdgeInsets.all(kSpace24), child: Column( mainAxisSize: MainAxisSize.min, children: [ Icon(icon, size: 48, color: theme.colorScheme.onSurfaceVariant), const SizedBox(height: kSpace12), Text( title, textAlign: TextAlign.center, style: theme.textTheme.titleMedium, ), if (subtitle != null && subtitle!.isNotEmpty) ...[ const SizedBox(height: kSpace4), Text( subtitle!, textAlign: TextAlign.center, style: theme.textTheme.bodySmall?.copyWith( color: theme.colorScheme.onSurfaceVariant, ), ), ], if (actionLabel != null) ...[ const SizedBox(height: kSpace16), FilledButton.tonal( onPressed: onAction, child: Text(actionLabel!), ), ], ], ), ), ); } }