import 'package:flutter/material.dart'; import '../theme/status_colors.dart'; import '../theme/theme_x.dart'; /// A dot + label badge encoding state — service up/down/unknown, backup or /// update success/fail, node reachable/unreachable. The same component /// everywhere a status appears so a given [Severity] always reads the same /// color, matching the design rule that status color is reserved and never /// doubles as the brand accent. class StatusPill extends StatelessWidget { const StatusPill({super.key, required this.label, required this.severity}); final String label; final Severity severity; @override Widget build(BuildContext context) { final color = severity.resolve(context.status, muted: context.colors.outline); return Container( padding: const EdgeInsets.fromLTRB(7, 3, 9, 3), decoration: BoxDecoration( // 8% tint, not 14% — measured against the dark surface, a same-hue // tint background caps critical's text contrast around ~3.5:1 no // matter the blend ratio (text and background converge toward the // same hue as alpha rises, and approach the plain-surface ceiling // as it falls); 8% is close to that ceiling while keeping // good/warning/serious comfortably at 4.5:1+. Below AA-for-text on // its own, mitigated the same way the design system's status // palette always mitigates this: label text, never color alone. color: severity == Severity.neutral ? context.colors.surfaceContainerHighest : Color.alphaBlend(color.withValues(alpha: 0.08), context.colors.surface), borderRadius: BorderRadius.circular(999), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Container( width: 6, height: 6, decoration: BoxDecoration(color: color, shape: BoxShape.circle), ), const SizedBox(width: 6), Text( label, style: context.text.labelMedium?.copyWith( color: severity == Severity.neutral ? context.colors.onSurfaceVariant : color, fontWeight: FontWeight.w600, ), ), ], ), ); } }