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? 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), ), ], ); } }