Files
photo-live/apps/mobile/lib/ui/components/empty_state.dart
T
2026-09-21 14:55:29 +08:00

77 lines
2.2 KiB
Dart

/// 空态(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!),
),
],
],
),
),
);
}
}