import 'package:flutter/material.dart'; import '../../core/theme/design_tokens.dart'; enum AppLoadingVariant { surface, inline, button } class AppLoadingIndicator extends StatelessWidget { const AppLoadingIndicator({ super.key, this.variant = AppLoadingVariant.surface, this.size, this.strokeWidth, this.color, this.trackColor, this.withContainer, }); final AppLoadingVariant variant; final double? size; final double? strokeWidth; final Color? color; final Color? trackColor; final bool? withContainer; double get _resolvedSize { return size ?? switch (variant) { AppLoadingVariant.surface => 22, AppLoadingVariant.inline => 16, AppLoadingVariant.button => 18, }; } double get _resolvedStrokeWidth { return strokeWidth ?? switch (variant) { AppLoadingVariant.surface => 2.2, AppLoadingVariant.inline => 2, AppLoadingVariant.button => 2.2, }; } Widget _buildSpinner(Color color, Color trackColor) { return SizedBox( width: _resolvedSize, height: _resolvedSize, child: CircularProgressIndicator( strokeWidth: _resolvedStrokeWidth, color: color, backgroundColor: trackColor, ), ); } @override Widget build(BuildContext context) { final colorScheme = Theme.of(context).colorScheme; final resolvedColor = color ?? switch (variant) { AppLoadingVariant.surface => colorScheme.primary, AppLoadingVariant.inline => colorScheme.onSurfaceVariant, AppLoadingVariant.button => colorScheme.onPrimary, }; final resolvedTrackColor = trackColor ?? switch (variant) { AppLoadingVariant.surface => colorScheme.primaryContainer, AppLoadingVariant.inline => colorScheme.outlineVariant, AppLoadingVariant.button => colorScheme.secondary, }; if (withContainer == false || (withContainer == null && switch (variant) { AppLoadingVariant.surface => true, AppLoadingVariant.inline => false, AppLoadingVariant.button => false, })) { return _buildSpinner(resolvedColor, resolvedTrackColor); } return Container( width: _resolvedSize + AppSpacing.md, height: _resolvedSize + AppSpacing.md, padding: const EdgeInsets.all(AppSpacing.xs), decoration: BoxDecoration( color: colorScheme.surface, borderRadius: BorderRadius.circular(AppRadius.full), border: Border.all(color: colorScheme.outlineVariant), boxShadow: [ BoxShadow( color: colorScheme.outlineVariant.withValues(alpha: 0.55), blurRadius: AppRadius.md, offset: const Offset(0, AppSpacing.xs), ), ], ), child: _buildSpinner(resolvedColor, resolvedTrackColor), ); } }