This commit is contained in:
2026-06-03 14:07:10 +08:00
parent 3bdece45c3
commit 9eb8d1cc37
118 changed files with 5689 additions and 2 deletions

View File

@@ -0,0 +1,100 @@
import 'package:flutter/material.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 = 44,
});
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);
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 const SizedBox.square(
dimension: 18,
child: CircularProgressIndicator(strokeWidth: 2),
);
}
if (icon == null) return Text(label);
return Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
icon!,
const SizedBox(width: 8),
Flexible(child: Text(label, overflow: TextOverflow.ellipsis)),
],
);
}
}