Files
worker/lib/core/widgets/custom_button.dart
2025-11-07 11:52:06 +07:00

139 lines
3.6 KiB
Dart

import 'package:flutter/material.dart';
import 'package:worker/core/theme/colors.dart';
/// Button variant types for different use cases.
enum ButtonVariant {
/// Primary button with filled background color
primary,
/// Secondary button with outlined border
secondary,
}
/// Custom button widget following the Worker app design system.
///
/// Supports primary and secondary variants, loading states, and disabled states.
///
/// Example usage:
/// ```dart
/// CustomButton(
/// text: 'Login',
/// onPressed: () => _handleLogin(),
/// variant: ButtonVariant.primary,
/// isLoading: _isLoading,
/// )
/// ```
class CustomButton extends StatelessWidget {
/// The text to display on the button
final String text;
/// Callback when button is pressed. If null, button is disabled.
final VoidCallback? onPressed;
/// Visual variant of the button (primary or secondary)
final ButtonVariant variant;
/// Whether to show loading indicator instead of text
final bool isLoading;
/// Optional icon to display before the text
final IconData? icon;
/// Custom width for the button. If null, uses parent constraints.
final double? width;
/// Custom height for the button. Defaults to 48.
final double? height;
const CustomButton({
super.key,
required this.text,
required this.onPressed,
this.variant = ButtonVariant.primary,
this.isLoading = false,
this.icon,
this.width,
this.height,
});
@override
Widget build(BuildContext context) {
final isDisabled = onPressed == null || isLoading;
if (variant == ButtonVariant.primary) {
return SizedBox(
width: width,
height: height ?? 48,
child: ElevatedButton(
onPressed: isDisabled ? null : onPressed,
style: ElevatedButton.styleFrom(
backgroundColor: AppColors.primaryBlue,
foregroundColor: Colors.white,
disabledBackgroundColor: AppColors.grey500,
disabledForegroundColor: Colors.white70,
elevation: 2,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
),
child: _buildContent(),
),
);
} else {
return SizedBox(
width: width,
height: height ?? 48,
child: OutlinedButton(
onPressed: isDisabled ? null : onPressed,
style: OutlinedButton.styleFrom(
foregroundColor: AppColors.primaryBlue,
disabledForegroundColor: AppColors.grey500,
side: BorderSide(
color: isDisabled ? AppColors.grey500 : AppColors.primaryBlue,
width: 1.5,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
),
child: _buildContent(),
),
);
}
}
/// Builds the button content (text, icon, or loading indicator)
Widget _buildContent() {
if (isLoading) {
return const SizedBox(
width: 20,
height: 20,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
),
);
}
if (icon != null) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(icon, size: 20),
const SizedBox(width: 8),
Text(
text,
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w500),
),
],
);
}
return Text(
text,
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w500),
);
}
}