105 lines
2.9 KiB
Dart
105 lines
2.9 KiB
Dart
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),
|
|
);
|
|
}
|
|
}
|