import 'package:flutter/material.dart'; import 'zen_style.dart'; /// A tab's big title and an optional line under it. class PageHeader extends StatelessWidget { const PageHeader({super.key, required this.title, this.subtitle, this.action}); final String title; final String? subtitle; /// A button beside the title, such as "New plan". final Widget? action; @override Widget build(BuildContext context) { final s = ZenStyle.of(context); final text = Theme.of(context).textTheme; return Padding( padding: const EdgeInsets.fromLTRB(20, 28, 20, 16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Expanded(child: Text(title, style: text.headlineLarge)), if (action != null) ...[const SizedBox(width: 12), action!], ], ), if (subtitle != null) ...[ const SizedBox(height: 6), Text(subtitle!, style: text.bodyLarge?.copyWith(color: s.inkMuted)), ], ], ), ); } } /// What an empty tab shows: what will appear here and how to get it there. class EmptyState extends StatelessWidget { const EmptyState({super.key, required this.icon, required this.title, required this.body}); final IconData icon; final String title; final String body; @override Widget build(BuildContext context) { final s = ZenStyle.of(context); final text = Theme.of(context).textTheme; return Padding( padding: const EdgeInsets.symmetric(horizontal: 20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( width: 56, height: 56, decoration: BoxDecoration( color: s.surfaceSoft, borderRadius: BorderRadius.circular(s.controlRadius.clamp(0, 28)), ), child: Icon(icon, color: s.accent), ), const SizedBox(height: 16), Text(title, style: text.titleLarge), const SizedBox(height: 6), ConstrainedBox( constraints: const BoxConstraints(maxWidth: 340), child: Text(body, style: text.bodyMedium?.copyWith(color: s.inkMuted)), ), ], ), ); } }