From b2f9ecadab7334a442e2bc3998e338e4c93b0177 Mon Sep 17 00:00:00 2001 From: Catrya <140891948+Catrya@users.noreply.github.com> Date: Wed, 23 Jul 2025 11:06:41 -0600 Subject: [PATCH] Improve info button UX and standardize dialog styling - Increase touch area for all info (i) icons with 8px padding - Fix line breaks in price type tooltip localization - Standardize payment method dialog buttons to match generate user dialog style - Update Confirm button to green background with black text and rounded borders --- .../key_manager/key_management_screen.dart | 33 +++-- lib/features/order/widgets/form_section.dart | 113 +++++++++--------- .../widgets/payment_methods_section.dart | 29 ++++- .../order/widgets/premium_section.dart | 1 + .../order/widgets/price_type_section.dart | 1 + lib/features/settings/about_screen.dart | 22 ++-- lib/features/settings/settings_screen.dart | 44 ++++--- lib/l10n/intl_en.arb | 4 +- lib/l10n/intl_es.arb | 4 +- lib/l10n/intl_it.arb | 4 +- 10 files changed, 152 insertions(+), 103 deletions(-) diff --git a/lib/features/key_manager/key_management_screen.dart b/lib/features/key_manager/key_management_screen.dart index 6a9e4578..cf9ee2b1 100644 --- a/lib/features/key_manager/key_management_screen.dart +++ b/lib/features/key_manager/key_management_screen.dart @@ -206,10 +206,13 @@ class _KeyManagementScreenState extends ConsumerState { S.of(context)!.secretWordsInfoText, ), borderRadius: BorderRadius.circular(12), - child: const Icon( - Icons.info_outline, - size: 20, - color: AppTheme.textSecondary, + child: const Padding( + padding: EdgeInsets.all(8.0), + child: Icon( + Icons.info_outline, + size: 20, + color: AppTheme.textSecondary, + ), ), ), ], @@ -320,10 +323,13 @@ class _KeyManagementScreenState extends ConsumerState { S.of(context)!.privacyInfoText, ), borderRadius: BorderRadius.circular(12), - child: const Icon( - Icons.info_outline, - size: 20, - color: AppTheme.textSecondary, + child: const Padding( + padding: EdgeInsets.all(8.0), + child: Icon( + Icons.info_outline, + size: 20, + color: AppTheme.textSecondary, + ), ), ), ], @@ -430,10 +436,13 @@ class _KeyManagementScreenState extends ConsumerState { S.of(context)!.currentTradeIndexInfoText, ), borderRadius: BorderRadius.circular(12), - child: const Icon( - Icons.info_outline, - size: 20, - color: AppTheme.textSecondary, + child: const Padding( + padding: EdgeInsets.all(8.0), + child: Icon( + Icons.info_outline, + size: 20, + color: AppTheme.textSecondary, + ), ), ), ], diff --git a/lib/features/order/widgets/form_section.dart b/lib/features/order/widgets/form_section.dart index a4296ceb..b526d99f 100644 --- a/lib/features/order/widgets/form_section.dart +++ b/lib/features/order/widgets/form_section.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:mostro_mobile/core/app_theme.dart'; +import 'package:mostro_mobile/generated/l10n.dart'; class FormSection extends StatelessWidget { final String title; @@ -8,6 +9,7 @@ class FormSection extends StatelessWidget { final Widget child; final Widget? extraContent; final String? infoTooltip; + final String? infoTitle; const FormSection({ super.key, @@ -17,6 +19,7 @@ class FormSection extends StatelessWidget { required this.child, this.extraContent, this.infoTooltip, + this.infoTitle, }); @override @@ -46,62 +49,16 @@ class FormSection extends StatelessWidget { ), if (infoTooltip != null) ...[ const SizedBox(width: 4), - GestureDetector( - onTap: () { - showDialog( - context: context, - builder: (context) => Dialog( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - backgroundColor: const Color(0xFF1E2230), - child: Padding( - padding: const EdgeInsets.all(20.0), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Padding( - padding: const EdgeInsets.symmetric( - horizontal: 8.0, vertical: 12.0), - child: Text( - infoTooltip!, - style: const TextStyle( - color: Colors.white, - fontSize: 16, - height: 1.4), - textAlign: TextAlign.center, - ), - ), - const SizedBox(height: 16), - SizedBox( - width: double.infinity, - child: ElevatedButton( - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF8CC63F), - foregroundColor: Colors.black, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - padding: const EdgeInsets.symmetric( - vertical: 12), - ), - onPressed: () => - Navigator.of(context).pop(), - child: const Text('OK', - style: TextStyle( - fontWeight: FontWeight.bold)), - ), - ), - ], - ), - ), - ), - ); - }, - child: Icon( - Icons.info_outline, - size: 14, - color: AppTheme.textSubtle, + InkWell( + onTap: () => _showInfoDialog(context, infoTitle ?? title, infoTooltip!), + borderRadius: BorderRadius.circular(12), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Icon( + Icons.info_outline, + size: 14, + color: AppTheme.textSubtle, + ), ), ), ], @@ -136,4 +93,48 @@ class FormSection extends StatelessWidget { ), ); } + + void _showInfoDialog(BuildContext context, String title, String content) { + showDialog( + context: context, + builder: (BuildContext dialogContext) { + return AlertDialog( + backgroundColor: AppTheme.backgroundCard, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), + side: BorderSide(color: Colors.white.withValues(alpha: 0.1)), + ), + title: Text( + title, + style: const TextStyle( + color: AppTheme.textPrimary, + fontSize: 18, + fontWeight: FontWeight.w600, + ), + ), + content: Text( + content, + style: const TextStyle( + color: AppTheme.textSecondary, + fontSize: 14, + height: 1.5, + ), + ), + actions: [ + TextButton( + onPressed: () => Navigator.of(dialogContext).pop(), + child: Text( + S.of(context)!.ok, + style: const TextStyle( + color: AppTheme.activeColor, + fontSize: 16, + fontWeight: FontWeight.w500, + ), + ), + ), + ], + ); + }, + ); + } } diff --git a/lib/features/order/widgets/payment_methods_section.dart b/lib/features/order/widgets/payment_methods_section.dart index b3ffcaf9..f697651c 100644 --- a/lib/features/order/widgets/payment_methods_section.dart +++ b/lib/features/order/widgets/payment_methods_section.dart @@ -4,6 +4,7 @@ import 'package:mostro_mobile/features/order/providers/payment_methods_provider. import 'package:mostro_mobile/features/order/widgets/form_section.dart'; import 'package:mostro_mobile/shared/providers/exchange_service_provider.dart'; import 'package:mostro_mobile/generated/l10n.dart'; +import 'package:mostro_mobile/core/app_theme.dart'; class PaymentMethodsSection extends ConsumerWidget { final List selectedMethods; @@ -183,17 +184,35 @@ class PaymentMethodsSection extends ConsumerWidget { actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), - child: Text(S.of(context)!.cancel, - style: const TextStyle(color: Colors.white70)), + child: Text( + S.of(context)!.cancel, + style: const TextStyle( + color: AppTheme.textSecondary, + fontSize: 16, + fontWeight: FontWeight.w500, + ), + ), ), - TextButton( + ElevatedButton( onPressed: () { onMethodsChanged( dialogSelectedMethods, dialogShowOtherField); Navigator.of(context).pop(); }, - child: Text(S.of(context)!.confirm, - style: const TextStyle(color: Color(0xFF8CC63F))), + style: ElevatedButton.styleFrom( + backgroundColor: AppTheme.activeColor, + foregroundColor: Colors.black, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + child: Text( + S.of(context)!.confirm, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + ), + ), ), ], ); diff --git a/lib/features/order/widgets/premium_section.dart b/lib/features/order/widgets/premium_section.dart index 77e5a91c..4f2f9091 100644 --- a/lib/features/order/widgets/premium_section.dart +++ b/lib/features/order/widgets/premium_section.dart @@ -27,6 +27,7 @@ class PremiumSection extends StatelessWidget { icon: premiumValueIcon, iconBackgroundColor: AppTheme.purpleAccent, // Purple color for premium infoTooltip: S.of(context)!.premiumTooltip, + infoTitle: S.of(context)!.premiumTitle, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ diff --git a/lib/features/order/widgets/price_type_section.dart b/lib/features/order/widgets/price_type_section.dart index 72b63383..371dc8e9 100644 --- a/lib/features/order/widgets/price_type_section.dart +++ b/lib/features/order/widgets/price_type_section.dart @@ -28,6 +28,7 @@ class PriceTypeSection extends StatelessWidget { iconBackgroundColor: AppTheme.purpleAccent.withValues( alpha: 0.3), // Purple color consistent with other sections infoTooltip: S.of(context)!.priceTypeTooltip, + infoTitle: S.of(context)!.priceType, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ diff --git a/lib/features/settings/about_screen.dart b/lib/features/settings/about_screen.dart index c28b8da4..97713564 100644 --- a/lib/features/settings/about_screen.dart +++ b/lib/features/settings/about_screen.dart @@ -520,10 +520,13 @@ class AboutScreen extends ConsumerWidget { InkWell( onTap: () => _showInfoDialog(context, label, explanation), borderRadius: BorderRadius.circular(12), - child: const Icon( - Icons.info_outline, - size: 16, - color: AppTheme.textSecondary, + child: const Padding( + padding: EdgeInsets.all(8.0), + child: Icon( + Icons.info_outline, + size: 16, + color: AppTheme.textSecondary, + ), ), ), ], @@ -561,10 +564,13 @@ class AboutScreen extends ConsumerWidget { InkWell( onTap: () => _showInfoDialog(context, label, explanation), borderRadius: BorderRadius.circular(12), - child: const Icon( - Icons.info_outline, - size: 16, - color: AppTheme.textSecondary, + child: const Padding( + padding: EdgeInsets.all(8.0), + child: Icon( + Icons.info_outline, + size: 16, + color: AppTheme.textSecondary, + ), ), ), const SizedBox(width: 6), diff --git a/lib/features/settings/settings_screen.dart b/lib/features/settings/settings_screen.dart index 2c208b37..04947c74 100644 --- a/lib/features/settings/settings_screen.dart +++ b/lib/features/settings/settings_screen.dart @@ -107,10 +107,13 @@ class SettingsScreen extends ConsumerWidget { S.of(context)!.languageInfoText, ), borderRadius: BorderRadius.circular(12), - child: const Icon( - Icons.info_outline, - size: 20, - color: AppTheme.textSecondary, + child: const Padding( + padding: EdgeInsets.all(8.0), + child: Icon( + Icons.info_outline, + size: 20, + color: AppTheme.textSecondary, + ), ), ), ], @@ -167,10 +170,13 @@ class SettingsScreen extends ConsumerWidget { S.of(context)!.currencyInfoText, ), borderRadius: BorderRadius.circular(12), - child: const Icon( - Icons.info_outline, - size: 20, - color: AppTheme.textSecondary, + child: const Padding( + padding: EdgeInsets.all(8.0), + child: Icon( + Icons.info_outline, + size: 20, + color: AppTheme.textSecondary, + ), ), ), ], @@ -227,10 +233,13 @@ class SettingsScreen extends ConsumerWidget { S.of(context)!.relaysInfoText, ), borderRadius: BorderRadius.circular(12), - child: const Icon( - Icons.info_outline, - size: 20, - color: AppTheme.textSecondary, + child: const Padding( + padding: EdgeInsets.all(8.0), + child: Icon( + Icons.info_outline, + size: 20, + color: AppTheme.textSecondary, + ), ), ), ], @@ -314,10 +323,13 @@ class SettingsScreen extends ConsumerWidget { S.of(context)!.mostroInfoText, ), borderRadius: BorderRadius.circular(12), - child: const Icon( - Icons.info_outline, - size: 20, - color: AppTheme.textSecondary, + child: const Padding( + padding: EdgeInsets.all(8.0), + child: Icon( + Icons.info_outline, + size: 20, + color: AppTheme.textSecondary, + ), ), ), ], diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index b3eb1f6e..bc7b47e3 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -392,7 +392,7 @@ "priceType": "Price type", "fixedPrice": "Fixed price", "market": "Market", - "priceTypeTooltip": "• Select Market Price if you want to use the price that Bitcoin has when someone takes your offer.\\n• Select Fixed Price if you want to define the exact amount of Bitcoin you will exchange.", + "priceTypeTooltip": "• Select Market Price if you want to use the price that Bitcoin has when someone takes your offer.\n\n• Select Fixed Price if you want to define the exact amount of Bitcoin you will exchange.", "@_comment_take_order_screen": "Take Order Screen Strings", "orderDetails": "ORDER DETAILS", @@ -633,7 +633,7 @@ "@_comment_settings_info_dialogs": "Settings Info Dialog Text", "languageInfoText": "Choose your preferred language for the application interface.", "currencyInfoText": "Choose the default currency for your orders.", - "relaysInfoText": "• Relays are servers that help distribute your messages across the Nostr network\n\n• Adding more relays can improve connectivity and redundancy\n\n• Relays don't sync with each other, so only those you're connected to will receive your messages.", + "relaysInfoText": "• Relays are servers that help distribute your messages across the Nostr network.\n\n• Adding more relays can improve connectivity and redundancy.\n\n• Relays don't sync with each other, so only those you're connected to will receive your messages.", "mostroInfoText": "• The Mostro you select will be the one where you post your offers.\n\n• In case of a dispute, a human assigned to that Mostro will be the one to resolve it.", "@_comment_account_info_dialogs": "Account Screen Info Dialog Text", diff --git a/lib/l10n/intl_es.arb b/lib/l10n/intl_es.arb index a8513b9f..80f86d9a 100644 --- a/lib/l10n/intl_es.arb +++ b/lib/l10n/intl_es.arb @@ -348,7 +348,7 @@ "priceType": "Tipo de precio", "fixedPrice": "Precio fijo", "market": "Mercado", - "priceTypeTooltip": "• Selecciona Precio de Mercado si quieres usar el precio que tiene Bitcoin cuando alguien tome tu oferta.\\n• Selecciona Precio Fijo si quieres definir la cantidad exacta de Bitcoin que intercambiarás.", + "priceTypeTooltip": "• Selecciona Precio de Mercado si quieres usar el precio que tiene Bitcoin cuando alguien tome tu oferta.\n\n• Selecciona Precio Fijo si quieres definir la cantidad exacta de Bitcoin que intercambiarás.", "withPremiumPercent": "con un +{premium}% de premio", "@withPremiumPercent": { @@ -663,7 +663,7 @@ "@_comment_settings_info_dialogs": "Texto de Diálogos de Información de Configuración", "languageInfoText": "Elige tu idioma preferido para la interfaz de la aplicación.", "currencyInfoText": "Elige la moneda predeterminada para tus órdenes.", - "relaysInfoText": "• Los relays son servidores que ayudan a distribuir tus mensajes a través de la red Nostr\n\n• Agregar más relays puede mejorar la conectividad y redundancia\n\n• Los relays no se sincronizan entre sí, por lo que solo aquellos a los que estés conectado recibirán tus mensajes.", + "relaysInfoText": "• Los relays son servidores que ayudan a distribuir tus mensajes a través de la red Nostr.\n\n• Agregar más relays puede mejorar la conectividad y redundancia.\n\n• Los relays no se sincronizan entre sí, por lo que solo aquellos a los que estés conectado recibirán tus mensajes.", "mostroInfoText": "• El Mostro que selecciones será donde publiques tus ofertas.\n\n• En caso de disputa, una persona asignada a ese Mostro será quien la resuelva.", "@_comment_account_info_dialogs": "Texto de Diálogos de Información de Cuenta", diff --git a/lib/l10n/intl_it.arb b/lib/l10n/intl_it.arb index 52a47110..c656d5b8 100644 --- a/lib/l10n/intl_it.arb +++ b/lib/l10n/intl_it.arb @@ -353,7 +353,7 @@ "priceType": "Tipo di prezzo", "fixedPrice": "Prezzo fisso", "market": "Mercato", - "priceTypeTooltip": "• Seleziona Prezzo di Mercato se vuoi usare il prezzo che ha Bitcoin quando qualcuno prende la tua offerta.\\n• Seleziona Prezzo Fisso se vuoi definire l'importo esatto di Bitcoin che scambierai.", + "priceTypeTooltip": "• Seleziona Prezzo di Mercato se vuoi usare il prezzo che ha Bitcoin quando qualcuno prende la tua offerta.\n\n• Seleziona Prezzo Fisso se vuoi definire l'importo esatto di Bitcoin che scambierai.", "withPremiumPercent": "con un +{premium}% di premio", "@withPremiumPercent": { @@ -671,7 +671,7 @@ "@_comment_settings_info_dialogs": "Testo Dialoghi Informazioni Impostazioni", "languageInfoText": "Scegli la tua lingua preferita per l'interfaccia dell'applicazione.", "currencyInfoText": "Scegli la valuta predefinita per i tuoi ordini.", - "relaysInfoText": "• I relay sono server che aiutano a distribuire i tuoi messaggi attraverso la rete Nostr\n\n• Aggiungere più relay può migliorare la connettività e la ridondanza\n\n• I relay non si sincronizzano tra loro, quindi solo quelli a cui sei connesso riceveranno i tuoi messaggi.", + "relaysInfoText": "• I relay sono server che aiutano a distribuire i tuoi messaggi attraverso la rete Nostr.\n\n• Aggiungere più relay può migliorare la connettività e la ridondanza.\n\n• I relay non si sincronizzano tra loro, quindi solo quelli a cui sei connesso riceveranno i tuoi messaggi.", "mostroInfoText": "• Il Mostro che selezioni sarà quello dove pubblicherai le tue offerte.\n\n• In caso di disputa, una persona assegnata a quel Mostro sarà quella che la risolverà.", "@_comment_account_info_dialogs": "Testo Dialoghi Informazioni Account",