TermRemoteCtl/apps/mobile_app/lib/app/ui_shell.dart

134 lines
3.2 KiB
Dart

import 'package:flutter/material.dart';
import 'app_theme.dart';
class AppPanel extends StatelessWidget {
const AppPanel({
super.key,
required this.child,
this.padding = AppTheme.panelPadding,
this.borderRadius = AppTheme.panelRadius,
});
final Widget child;
final EdgeInsetsGeometry padding;
final BorderRadiusGeometry borderRadius;
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
return DecoratedBox(
decoration: BoxDecoration(
color: colorScheme.surfaceContainerHighest,
borderRadius: borderRadius,
border: Border.all(color: colorScheme.outlineVariant),
),
child: Padding(padding: padding, child: child),
);
}
}
class AppSectionHeader extends StatelessWidget {
const AppSectionHeader({
super.key,
required this.eyebrow,
required this.title,
required this.subtitle,
});
final String eyebrow;
final String title;
final String subtitle;
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(eyebrow, style: Theme.of(context).textTheme.labelLarge),
const SizedBox(height: 8),
Text(title, style: Theme.of(context).textTheme.headlineSmall),
const SizedBox(height: 4),
Text(subtitle, style: Theme.of(context).textTheme.bodySmall),
],
);
}
}
class AppEmptyState extends StatelessWidget {
const AppEmptyState({
super.key,
required this.icon,
required this.title,
required this.message,
});
final IconData icon;
final String title;
final String message;
@override
Widget build(BuildContext context) {
return AppPanel(
child: Column(
children: [
Icon(icon, size: 56, color: Theme.of(context).colorScheme.primary),
const SizedBox(height: 16),
Text(
title,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(height: 8),
Text(
message,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.bodyMedium,
),
],
),
);
}
}
class StatusPill extends StatelessWidget {
const StatusPill({
super.key,
required this.label,
required this.icon,
required this.color,
});
final String label;
final IconData icon;
final Color color;
@override
Widget build(BuildContext context) {
return DecoratedBox(
decoration: BoxDecoration(
color: color.withValues(alpha: 0.14),
borderRadius: BorderRadius.circular(999),
border: Border.all(color: color.withValues(alpha: 0.24)),
),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(icon, size: 16, color: color),
const SizedBox(width: 6),
Text(
label,
style: Theme.of(context).textTheme.labelMedium?.copyWith(
color: color,
fontWeight: FontWeight.w700,
),
),
],
),
),
);
}
}