Files
PeachDeployments/lib/Peach/designs/StatCard.dart
alvocool 38881d1fe1 Add app source and tests
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-11 10:15:30 +03:00

100 lines
3.0 KiB
Dart

import 'package:flutter/material.dart';
import '../about/internal/application/TextType.dart';
import '../utils/Colors.dart';
import 'text/Text.dart';
/// A horizontal metric card: icon chip on the left, big value + label on the
/// right, with an optional trailing accent (e.g. a mini ring or delta).
class StatCard extends StatelessWidget {
final IconData icon;
final String label;
final String value;
final Color color;
final String? sub;
final Widget? trailing;
const StatCard({
super.key,
required this.icon,
required this.label,
required this.value,
required this.color,
this.sub,
this.trailing,
});
@override
Widget build(BuildContext context) {
final jp = context.jp;
return Container(
padding: const EdgeInsets.all(16),
decoration: PeachTheme.panel(context, glowColor: color, radius: 18),
child: Row(
children: [
Container(
width: 46,
height: 46,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
color.withValues(alpha: 0.32),
color.withValues(alpha: 0.14),
],
),
borderRadius: BorderRadius.circular(13),
border: Border.all(color: color.withValues(alpha: 0.40)),
boxShadow: PeachTheme.glow(color, opacity: 0.22, blur: 16),
),
child: Icon(icon, color: color, size: 22),
),
const SizedBox(width: 14),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
text(
value,
25,
TextType.Bold,
color: jp.text,
maxLines: 1,
overflow: TextOverflow.ellipsis,
letterSpacing: -0.6,
height: 1.05,
weight: FontWeight.w800,
),
const SizedBox(height: 2),
text(
label.toUpperCase(),
10.5,
TextType.Regular,
color: jp.textFaint,
maxLines: 1,
overflow: TextOverflow.ellipsis,
letterSpacing: 0.8,
weight: FontWeight.w700,
),
if (sub != null)
text(
sub!,
11,
TextType.Regular,
weight: FontWeight.w400,
color: jp.textDim,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
],
),
),
if (trailing != null) ...[const SizedBox(width: 8), trailing!],
],
),
);
}
}