Files
please-pay-me/mobile/lib/ui/atoms/app_text_field.dart
T
2026-09-21 04:06:43 +03:00

97 lines
3.2 KiB
Dart

import 'package:flutter/cupertino.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:please_pay_me/theme/tokens.dart';
import 'package:please_pay_me/ui/atoms/app_text.dart';
/// Rounded iOS text field with optional grouped-style caption and error.
class AppTextField extends StatelessWidget {
const AppTextField({
super.key,
this.label,
this.placeholder,
this.controller,
this.onChanged,
this.keyboardType,
this.obscureText = false,
this.enabled = true,
this.errorText,
this.prefixIcon,
this.clearable = true,
this.maxLines = 1,
});
final String? label;
final String? placeholder;
final TextEditingController? controller;
final ValueChanged<String>? onChanged;
final TextInputType? keyboardType;
final bool obscureText;
final bool enabled;
final String? errorText;
final IconData? prefixIcon;
final bool clearable;
final int maxLines;
@override
Widget build(BuildContext context) {
final hasError = errorText != null && errorText!.isNotEmpty;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (label != null) AppSectionHeader(label!, padding: const EdgeInsets.only(bottom: AppSpacing.s2)),
Opacity(
opacity: enabled ? 1 : 0.4,
child: CupertinoTextField(
controller: controller,
onChanged: onChanged,
keyboardType: keyboardType,
obscureText: obscureText,
enabled: enabled,
maxLines: maxLines,
placeholder: placeholder,
clearButtonMode: clearable ? OverlayVisibilityMode.editing : OverlayVisibilityMode.never,
padding: const EdgeInsets.symmetric(
horizontal: AppSpacing.s3,
vertical: AppSpacing.s3,
),
prefix: prefixIcon == null
? null
: Padding(
padding: const EdgeInsets.only(left: AppSpacing.s3),
child: Icon(
prefixIcon,
size: 20,
color: AppColors.of(context, AppColors.secondaryLabel),
),
),
placeholderStyle: GoogleFonts.inter(
textStyle: AppTypography.body,
color: AppColors.of(context, AppColors.tertiaryLabel),
),
style: GoogleFonts.inter(
textStyle: AppTypography.body,
color: AppColors.of(context, AppColors.label),
),
decoration: BoxDecoration(
color: AppColors.of(context, AppColors.groupedSurface),
borderRadius: BorderRadius.circular(AppRadii.md),
border: Border.all(
color: hasError
? AppColors.of(context, AppColors.systemRed)
: AppColors.of(context, AppColors.opaqueSeparator),
width: AppSizes.hairline,
),
),
),
),
if (hasError)
Padding(
padding: const EdgeInsets.only(top: AppSpacing.s2, left: AppSpacing.s1),
child: AppText.footnote(errorText!, color: AppColors.systemRed),
),
],
);
}
}