improve dialog box design (#3145)
malik1004x committed
Apr 2, 2026 at 13:04 UTC
ac410f40c92fb7a3c058eefe30fe5d14b974513e
4 files changed
+169
-127
lib/src/screens/backup/backup_page.dart
+3
@@ -3,6 +3,7 @@ import 'dart:ui';
3
import 'package:cake_wallet/core/execution_state.dart';
4
import 'package:cake_wallet/src/screens/base_page.dart';
5
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
6
+import 'package:cake_wallet/src/widgets/base_alert_dialog.dart';
7
import 'package:cake_wallet/src/widgets/primary_button.dart';
8
import 'package:cake_wallet/generated/i18n.dart';
9
import 'package:cake_wallet/routes.dart';
@@ -116,6 +117,8 @@ class BackupPage extends BasePage {
117
alertContent: S.of(context).save_backup_password,
118
rightButtonText: S.of(context).seed_alert_yes,
119
leftButtonText: S.of(context).seed_alert_back,
120
+ leftAlertButtonStyle: AlertButtonStyle.error(context),
121
+ rightAlertButtonStyle: AlertButtonStyle.secondary(context),
122
actionRightButton: () async {
123
Navigator.of(dialogContext).pop();
124
final backupFuture = backupViewModelBase.exportBackup();
lib/src/widgets/alert_with_one_action.dart
+35
-28
@@ -39,32 +39,39 @@ class AlertWithOneAction extends BaseAlertDialog {
39
String? get headerText => headerTitleText;
40
41
@override
42
- Widget actionButtons(BuildContext context) {
43
- return Container(
44
- width: 300,
45
- height: 52,
46
- padding: EdgeInsets.only(left: 12, right: 12),
47
- color: Theme.of(context).colorScheme.surface,
48
- child: ButtonTheme(
49
- minWidth: double.infinity,
50
- child: TextButton(
51
- key: buttonKey,
52
- onPressed: buttonAction,
53
- // FIX-ME: Style
54
- //highlightColor: Colors.transparent,
55
- //splashColor: Colors.transparent,
56
- child: Text(
57
- buttonText,
58
- textAlign: TextAlign.center,
59
- style: Theme.of(context).textTheme.bodyMedium!.copyWith(
60
- fontSize: 15,
61
- fontWeight: FontWeight.w600,
62
- color: Theme.of(context).colorScheme.primary,
63
- decoration: TextDecoration.none,
64
- ),
65
- ),
66
- ),
67
- ),
68
- );
69
- }
42
+ VoidCallback get actionRight => buttonAction;
43
+
44
+ @override
45
+ bool get showLeftButton => false;
46
+
47
+ @override
48
+ String get rightActionButtonText => buttonText;
49
+
50
+ // @override
51
+ // Widget actionButtons(BuildContext context) {
52
+ // return Container(
53
+ // padding: EdgeInsets.only(left: 12, right: 12),
54
+ // color: Theme.of(context).colorScheme.surface,
55
+ // child: ButtonTheme(
56
+ // minWidth: double.infinity,
57
+ // child: TextButton(
58
+ // key: buttonKey,
59
+ // onPressed: buttonAction,
60
+ // // FIX-ME: Style
61
+ // //highlightColor: Colors.transparent,
62
+ // //splashColor: Colors.transparent,
63
+ // child: Text(
64
+ // buttonText,
65
+ // textAlign: TextAlign.center,
66
+ // style: Theme.of(context).textTheme.bodyMedium!.copyWith(
67
+ // fontSize: 15,
68
+ // fontWeight: FontWeight.w600,
69
+ // color: Theme.of(context).colorScheme.primary,
70
+ // decoration: TextDecoration.none,
71
+ // ),
72
+ // ),
73
+ // ),
74
+ // ),
75
+ // );
76
+ // }
77
}
lib/src/widgets/alert_with_two_actions.dart
+6
@@ -14,6 +14,8 @@ class AlertWithTwoActions extends BaseAlertDialog {
14
this.isDividerExist = false,
15
// this.leftActionColor,
16
// this.rightActionColor,
17
+ this.leftAlertButtonStyle,
18
+ this.rightAlertButtonStyle,
19
this.alertRightActionButtonKey,
20
this.alertLeftActionButtonKey,
21
this.alertDialogKey,
@@ -29,6 +31,10 @@ class AlertWithTwoActions extends BaseAlertDialog {
31
final bool alertBarrierDismissible;
32
// final Color leftActionColor;
33
// final Color rightActionColor;
34
+ @override
35
+ final AlertButtonStyle? leftAlertButtonStyle;
36
+ @override
37
+ final AlertButtonStyle? rightAlertButtonStyle;
38
final bool isDividerExist;
39
final Key? alertRightActionButtonKey;
40
final Key? alertLeftActionButtonKey;
lib/src/widgets/base_alert_dialog.dart
+125
-99
@@ -1,14 +1,45 @@
1
import 'dart:ui';
2
3
+import 'package:auto_size_text/auto_size_text.dart';
4
import 'package:cake_wallet/src/widgets/section_divider.dart';
5
import 'package:flutter/material.dart';
6
7
+
8
+class AlertButtonStyle {
9
+ final Color backgroundColor;
10
+ final Color textColor;
11
+ final FontWeight fontWeight;
12
+
13
+ const AlertButtonStyle({
14
+ required this.backgroundColor,
15
+ required this.textColor,
16
+ this.fontWeight = FontWeight.w400
17
+ });
18
+
19
+ factory AlertButtonStyle.primary(BuildContext context) => AlertButtonStyle(
20
+ backgroundColor: Theme.of(context).colorScheme.primary,
21
+ textColor: Theme.of(context).colorScheme.onPrimary,
22
+ );
23
+
24
+ factory AlertButtonStyle.secondary(BuildContext context) => AlertButtonStyle(
25
+ backgroundColor: Theme.of(context).colorScheme.surfaceContainer,
26
+ textColor: Theme.of(context).colorScheme.primary,
27
+ );
28
+
29
+ factory AlertButtonStyle.error(BuildContext context) => AlertButtonStyle(
30
+ backgroundColor: Theme.of(context).colorScheme.errorContainer,
31
+ textColor: Theme.of(context).colorScheme.error,
32
+ fontWeight: FontWeight.w500
33
+ );
34
+}
35
+
36
+
37
class BaseAlertDialog extends StatelessWidget {
38
String? get headerText => '';
39
40
String? get titleText => '';
41
11
- double? get titleTextSize => 20;
42
+ double? get titleTextSize => 18;
43
44
String get contentText => '';
45
@@ -28,14 +59,6 @@ class BaseAlertDialog extends StatelessWidget {
59
60
bool get barrierDismissible => true;
61
31
- Color? get leftActionButtonTextColor => null;
32
-
33
- Color? get rightActionButtonTextColor => null;
34
-
35
- Color? get leftActionButtonColor => null;
36
-
37
- Color? get rightActionButtonColor => null;
38
-
62
String? get headerImageUrl => null;
63
64
Key? leftActionButtonKey;
@@ -43,6 +66,12 @@ class BaseAlertDialog extends StatelessWidget {
66
Key? rightActionButtonKey;
67
68
Key? dialogKey;
69
+
70
+ AlertButtonStyle? get leftAlertButtonStyle => null;
71
+
72
+ AlertButtonStyle? get rightAlertButtonStyle => null;
73
+
74
+ bool get showLeftButton => true;
75
76
Widget title(BuildContext context) {
77
return Text(
@@ -83,7 +112,7 @@ class BaseAlertDialog extends StatelessWidget {
112
contentText,
113
textAlign: TextAlign.center,
114
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
86
- fontSize: 16,
115
+ fontSize: 14,
116
decoration: TextDecoration.none,
117
),
118
),
@@ -93,59 +122,56 @@ class BaseAlertDialog extends StatelessWidget {
122
}
123
124
Widget actionButtons(BuildContext context) {
96
- return Container(
97
- height: 60,
98
- child: Row(
99
- mainAxisSize: MainAxisSize.max,
100
- crossAxisAlignment: CrossAxisAlignment.stretch,
101
- children: <Widget>[
102
- Expanded(
103
- child: TextButton(
104
- key: leftActionButtonKey,
105
- onPressed: actionLeft,
106
- style: TextButton.styleFrom(
107
- backgroundColor: leftActionButtonColor ?? Theme.of(context).colorScheme.surface,
108
- shape: const RoundedRectangleBorder(
109
- borderRadius: BorderRadius.all(Radius.zero),
125
+ final rightButtonStyle = rightAlertButtonStyle ?? AlertButtonStyle.primary(context);
126
+ final leftButtonStyle = leftAlertButtonStyle ?? AlertButtonStyle.secondary(context);
127
+
128
+ return Row(
129
+ mainAxisAlignment: MainAxisAlignment.center,
130
+ mainAxisSize: MainAxisSize.max,
131
+ spacing:8,
132
+ children: <Widget>[
133
+ if(showLeftButton)
134
+ Expanded(
135
+ child: GestureDetector(
136
+ key: leftActionButtonKey,
137
+ onTap: actionLeft,
138
+ child: Container(
139
+ decoration: BoxDecoration(
140
+ borderRadius: BorderRadius.circular(999999),
141
+ color: leftButtonStyle.backgroundColor
142
+ ),
143
+ child: Padding(
144
+ padding: EdgeInsets.symmetric(vertical: 16, horizontal: 8),
145
+ child: AutoSizeText(
146
+ maxLines:1,
147
+ leftActionButtonText,
148
+ textAlign: TextAlign.center,
149
+ style: TextStyle(fontSize: 16, color: leftButtonStyle.textColor, fontWeight: leftButtonStyle.fontWeight)
150
),
151
),
112
- child: Text(
113
- leftActionButtonText,
114
- textAlign: TextAlign.center,
115
- style: Theme.of(context).textTheme.bodyMedium!.copyWith(
116
- fontSize: 15,
117
- fontWeight: FontWeight.w600,
118
- color: leftActionButtonTextColor ??
119
- Theme.of(context).colorScheme.errorContainer,
120
- decoration: TextDecoration.none,
121
- ),
122
- )),
123
- ),
124
- const VerticalSectionDivider(),
125
- Expanded(
126
- child: TextButton(
152
+ )),
153
+ ),
154
+ Expanded(
155
+ child: GestureDetector(
156
key: rightActionButtonKey,
128
- onPressed: actionRight,
129
- style: TextButton.styleFrom(
130
- backgroundColor: rightActionButtonColor ?? Theme.of(context).colorScheme.surface,
131
- shape: const RoundedRectangleBorder(
132
- borderRadius: BorderRadius.all(Radius.zero),
157
+ onTap: actionRight,
158
+ child: Container(
159
+ decoration: BoxDecoration(
160
+ borderRadius: BorderRadius.circular(999999),
161
+ color: rightButtonStyle.backgroundColor
162
),
134
- ),
135
- child: Text(
136
- rightActionButtonText,
137
- textAlign: TextAlign.center,
138
- style: Theme.of(context).textTheme.bodyMedium!.copyWith(
139
- fontSize: 15,
140
- fontWeight: FontWeight.w600,
141
- color: rightActionButtonTextColor ?? Theme.of(context).colorScheme.onSurface,
142
- decoration: TextDecoration.none,
143
- ),
144
- ),
145
- ),
146
- ),
147
- ],
148
- ),
163
+ child: Padding(
164
+ padding: EdgeInsets.symmetric(vertical: 16, horizontal: 8),
165
+ child: AutoSizeText(
166
+ maxLines: 1,
167
+ rightActionButtonText,
168
+ textAlign: TextAlign.center,
169
+ style: TextStyle(fontSize: 16, color: rightButtonStyle.textColor, fontWeight: rightButtonStyle.fontWeight)
170
+ ),
171
+ ),
172
+ )),
173
+ ),
174
+ ],
175
);
176
}
177
@@ -178,53 +204,53 @@ class BaseAlertDialog extends StatelessWidget {
204
filter: ImageFilter.blur(sigmaX: 3.0, sigmaY: 3.0),
205
child: Container(
206
decoration:
181
- BoxDecoration(color: Theme.of(context).colorScheme.surface.withOpacity(0.8)),
207
+ BoxDecoration(color: Theme.of(context).colorScheme.onSurface.withAlpha(25)),
208
child: Center(
183
- child: GestureDetector(
184
- onTap: () => null,
185
- child: Container(
186
- decoration: BoxDecoration(
187
- borderRadius: BorderRadius.circular(30),
188
- color: Theme.of(context).colorScheme.surface,
189
- ),
190
- width: 300,
191
- child: Stack(
192
- clipBehavior: Clip.none,
193
- children: [
194
- if (headerImageUrl != null) headerImage(context, headerImageUrl!),
195
- Column(
196
- mainAxisSize: MainAxisSize.min,
197
- children: <Widget>[
198
- if (headerImageUrl != null) const SizedBox(height: 50),
209
+ child: Padding(
210
+ padding: const EdgeInsets.all(16.0),
211
+ child: GestureDetector(
212
+ onTap: () => null,
213
+ child: Container(
214
+ decoration: BoxDecoration(
215
+ borderRadius: BorderRadius.circular(24),
216
+ color: Theme.of(context).colorScheme.surface,
217
+ ),
218
+ child: Padding(
219
+ padding: const EdgeInsets.all(24.0),
220
+ child: Stack(
221
+ clipBehavior: Clip.none,
222
+ children: [
223
+ if (headerImageUrl != null) headerImage(context, headerImageUrl!),
224
Column(
200
- crossAxisAlignment: CrossAxisAlignment.center,
225
+ mainAxisSize: MainAxisSize.min,
226
children: <Widget>[
202
- if (headerText?.isNotEmpty ?? false) headerTitle(context),
203
- titleText != null
204
- ? Padding(
205
- padding: EdgeInsets.fromLTRB(24, 20, 24, 0),
206
- child: title(context),
207
- )
208
- : SizedBox(height: 16),
209
- isDividerExists
210
- ? Padding(
211
- padding: EdgeInsets.only(top: 16, bottom: 8),
212
- child: const HorizontalSectionDivider(),
213
- )
214
- : Offstage(),
215
- Padding(
216
- padding: EdgeInsets.fromLTRB(24, 8, 24, 32),
217
- child: content(context),
218
- )
227
+ if (headerImageUrl != null) const SizedBox(height: 50),
228
+ Column(
229
+ crossAxisAlignment: CrossAxisAlignment.center,
230
+ children: <Widget>[
231
+ if (headerText?.isNotEmpty ?? false) headerTitle(context),
232
+ titleText != null
233
+ ? title(context)
234
+ : SizedBox(height: 16),
235
+ isDividerExists
236
+ ? Padding(
237
+ padding: EdgeInsets.only(top: 16, bottom: 8),
238
+ child: const HorizontalSectionDivider(),
239
+ )
240
+ : Offstage(),
241
+ Padding(
242
+ padding: EdgeInsets.symmetric(vertical: 25),
243
+ child: content(context),
244
+ )
245
+ ],
246
+ ),
247
+ // if (isBottomDividerExists) const HorizontalSectionDivider(),
248
+ actionButtons(context)
249
],
250
),
221
- if (isBottomDividerExists) const HorizontalSectionDivider(),
222
- ClipRRect(
223
- borderRadius: BorderRadius.all(Radius.circular(30)),
224
- child: actionButtons(context))
251
],
252
),
227
- ],
253
+ ),
254
),
255
),
256
),