Files
record-tool/lib/shared/widgets/app_button.dart
2026-06-04 14:34:46 +08:00

102 lines
2.5 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
enum AppButtonVariant { primary, secondary, outline, text, danger }
class AppButton extends StatelessWidget {
const AppButton({
super.key,
required this.label,
this.onPressed,
this.icon,
this.variant = AppButtonVariant.primary,
this.isLoading = false,
this.expand = false,
this.height,
});
final String label;
final VoidCallback? onPressed;
final Widget? icon;
final AppButtonVariant variant;
final bool isLoading;
final bool expand;
final double? height;
@override
Widget build(BuildContext context) {
final child = _ButtonContent(
label: label,
icon: icon,
isLoading: isLoading,
);
final enabled = isLoading ? null : onPressed;
final size = Size(expand ? double.infinity : 0, height ?? 44.h);
return switch (variant) {
AppButtonVariant.primary => ElevatedButton(
onPressed: enabled,
style: ElevatedButton.styleFrom(minimumSize: size),
child: child,
),
AppButtonVariant.secondary => FilledButton.tonal(
onPressed: enabled,
style: FilledButton.styleFrom(minimumSize: size),
child: child,
),
AppButtonVariant.outline => OutlinedButton(
onPressed: enabled,
style: OutlinedButton.styleFrom(minimumSize: size),
child: child,
),
AppButtonVariant.text => TextButton(
onPressed: enabled,
style: TextButton.styleFrom(minimumSize: size),
child: child,
),
AppButtonVariant.danger => FilledButton(
onPressed: enabled,
style: FilledButton.styleFrom(
minimumSize: size,
backgroundColor: Theme.of(context).colorScheme.error,
),
child: child,
),
};
}
}
class _ButtonContent extends StatelessWidget {
const _ButtonContent({
required this.label,
required this.isLoading,
this.icon,
});
final String label;
final Widget? icon;
final bool isLoading;
@override
Widget build(BuildContext context) {
if (isLoading) {
return SizedBox.square(
dimension: 18.r,
child: CircularProgressIndicator(strokeWidth: 2.r),
);
}
if (icon == null) return Text(label);
return Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
icon!,
SizedBox(width: 8.w),
Flexible(child: Text(label, overflow: TextOverflow.ellipsis)),
],
);
}
}