Skip to content

Commit 48688a8

Browse files
committed
feat: add dark theme to auth screen
1 parent 2a401b1 commit 48688a8

7 files changed

Lines changed: 193 additions & 75 deletions

File tree

src/lib/core/theme/auth_layout_template.dart

Lines changed: 83 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -34,36 +34,59 @@ class AuthLayoutTemplate extends StatelessWidget {
3434

3535
@override
3636
Widget build(BuildContext context) {
37+
final isDark = Theme.of(context).brightness == Brightness.dark;
38+
3739
return Scaffold(
3840
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
3941
appBar: AppBar(
4042
backgroundColor: Colors.transparent,
4143
elevation: 0,
4244
leading: Navigator.canPop(context)
4345
? IconButton(
44-
icon: Icon(
45-
Icons.arrow_back,
46-
color: Theme.of(context).colorScheme.primary,
46+
icon: Container(
47+
width: 40,
48+
height: 40,
49+
decoration: BoxDecoration(
50+
shape: BoxShape.circle,
51+
color: isDark
52+
? const Color(0xFF172744)
53+
: Theme.of(context).colorScheme.surface,
54+
),
55+
child: Icon(
56+
Icons.arrow_back,
57+
color: Theme.of(context).colorScheme.primary,
58+
),
4759
),
4860
onPressed: () => Navigator.pop(context),
4961
)
5062
: null,
5163
),
52-
body: SafeArea(
53-
child: Center(
54-
child: SingleChildScrollView(
55-
padding: const EdgeInsets.fromLTRB(24.0, 16.0, 24.0, 48.0),
56-
child: Column(
57-
mainAxisAlignment: MainAxisAlignment.center,
58-
children: [
59-
_buildHeader(context),
60-
const SizedBox(height: 32),
61-
useCard
62-
? _buildCardContainer(context)
63-
: _buildTransparentContainer(context),
64-
const SizedBox(height: 32),
65-
if (footerContent != null) footerContent!,
66-
],
64+
body: Container(
65+
decoration: BoxDecoration(
66+
gradient: isDark
67+
? const LinearGradient(
68+
begin: Alignment.topCenter,
69+
end: Alignment.bottomCenter,
70+
colors: [Color(0xFF08142D), Color(0xFF0B1A38), Color(0xFF0A1834)],
71+
)
72+
: null,
73+
),
74+
child: SafeArea(
75+
child: Center(
76+
child: SingleChildScrollView(
77+
padding: const EdgeInsets.fromLTRB(24.0, 16.0, 24.0, 48.0),
78+
child: Column(
79+
mainAxisAlignment: MainAxisAlignment.center,
80+
children: [
81+
_buildHeader(context),
82+
const SizedBox(height: 32),
83+
useCard
84+
? _buildCardContainer(context)
85+
: _buildTransparentContainer(context),
86+
const SizedBox(height: 32),
87+
if (footerContent != null) footerContent!,
88+
],
89+
),
6790
),
6891
),
6992
),
@@ -72,18 +95,20 @@ class AuthLayoutTemplate extends StatelessWidget {
7295
}
7396

7497
Widget _buildHeader(BuildContext context) {
98+
final isDark = Theme.of(context).brightness == Brightness.dark;
99+
75100
return Column(
76101
children: [
77102
customHeaderIcon ??
78103
Container(
79104
width: 80,
80105
height: 80,
81106
decoration: BoxDecoration(
82-
color: Theme.of(context).colorScheme.surface,
107+
color: isDark ? const Color(0xFF1E2B47) : Theme.of(context).colorScheme.surface,
83108
borderRadius: BorderRadius.circular(24),
84109
boxShadow: [
85110
BoxShadow(
86-
color: Theme.of(context).colorScheme.primary.withOpacity(0.1),
111+
color: Theme.of(context).colorScheme.primary.withValues(alpha: 0.14),
87112
blurRadius: 20,
88113
offset: const Offset(0, 10),
89114
),
@@ -122,14 +147,17 @@ class AuthLayoutTemplate extends StatelessWidget {
122147
}
123148

124149
Widget _buildCardContainer(BuildContext context) {
150+
final isDark = Theme.of(context).brightness == Brightness.dark;
151+
125152
return Container(
126153
padding: const EdgeInsets.all(32),
127154
decoration: BoxDecoration(
128-
color: Theme.of(context).colorScheme.surface,
155+
color: isDark ? const Color(0xFF1A2945) : Theme.of(context).colorScheme.surface,
129156
borderRadius: BorderRadius.circular(32),
157+
border: isDark ? Border.all(color: const Color(0xFF2A3E62), width: 1) : null,
130158
boxShadow: [
131159
BoxShadow(
132-
color: Theme.of(context).colorScheme.primary.withOpacity(0.08),
160+
color: Theme.of(context).colorScheme.primary.withValues(alpha: 0.12),
133161
blurRadius: 30,
134162
offset: const Offset(0, 10),
135163
),
@@ -143,6 +171,8 @@ class AuthLayoutTemplate extends StatelessWidget {
143171
_buildFormElements(context);
144172

145173
Widget _buildFormElements(BuildContext context) {
174+
final isDark = Theme.of(context).brightness == Brightness.dark;
175+
146176
return Column(
147177
crossAxisAlignment: CrossAxisAlignment.stretch,
148178
children: [
@@ -154,12 +184,15 @@ class AuthLayoutTemplate extends StatelessWidget {
154184
style: ElevatedButton.styleFrom(
155185
backgroundColor: Theme.of(context).colorScheme.primary,
156186
disabledBackgroundColor:
157-
Theme.of(context).colorScheme.primary.withOpacity(0.6),
187+
Theme.of(context).colorScheme.primary.withValues(alpha: 0.6),
158188
padding: const EdgeInsets.symmetric(vertical: 20),
159189
shape: RoundedRectangleBorder(
160190
borderRadius: BorderRadius.circular(16),
161191
),
162-
elevation: isLoading ? 0 : 4,
192+
elevation: isLoading ? 0 : (isDark ? 8 : 4),
193+
shadowColor: isDark
194+
? Theme.of(context).colorScheme.primary.withValues(alpha: 0.35)
195+
: null,
163196
),
164197
child: isLoading
165198
? SizedBox(
@@ -197,11 +230,15 @@ class AuthLayoutTemplate extends StatelessWidget {
197230
Expanded(
198231
child: Divider(color: Theme.of(context).colorScheme.outline),
199232
),
200-
const Padding(
233+
Padding(
201234
padding: EdgeInsets.symmetric(horizontal: 16),
202235
child: Text(
203236
'OR',
204-
style: TextStyle(fontSize: 10, fontWeight: FontWeight.bold),
237+
style: TextStyle(
238+
fontSize: 10,
239+
fontWeight: FontWeight.bold,
240+
color: Theme.of(context).colorScheme.onSurfaceVariant,
241+
),
205242
),
206243
),
207244
Expanded(
@@ -214,6 +251,16 @@ class AuthLayoutTemplate extends StatelessWidget {
214251
children: [
215252
Expanded(
216253
child: OutlinedButton.icon(
254+
style: OutlinedButton.styleFrom(
255+
foregroundColor: Theme.of(context).colorScheme.onSurface,
256+
side: BorderSide(color: Theme.of(context).colorScheme.outline),
257+
backgroundColor:
258+
isDark ? const Color(0xFF1A2945) : Theme.of(context).colorScheme.surface,
259+
shape: RoundedRectangleBorder(
260+
borderRadius: BorderRadius.circular(16),
261+
),
262+
padding: const EdgeInsets.symmetric(vertical: 14),
263+
),
217264
onPressed: onGoogleTap,
218265
icon: const Icon(
219266
Icons.g_mobiledata,
@@ -226,6 +273,16 @@ class AuthLayoutTemplate extends StatelessWidget {
226273
const SizedBox(width: 16),
227274
Expanded(
228275
child: OutlinedButton.icon(
276+
style: OutlinedButton.styleFrom(
277+
foregroundColor: Theme.of(context).colorScheme.onSurface,
278+
side: BorderSide(color: Theme.of(context).colorScheme.outline),
279+
backgroundColor:
280+
isDark ? const Color(0xFF1A2945) : Theme.of(context).colorScheme.surface,
281+
shape: RoundedRectangleBorder(
282+
borderRadius: BorderRadius.circular(16),
283+
),
284+
padding: const EdgeInsets.symmetric(vertical: 14),
285+
),
229286
onPressed: onFacebookTap,
230287
icon: const Icon(Icons.facebook, color: Color(0xFF1877F2)),
231288
label: const Text('Facebook'),

src/lib/core/theme/custom_text_field.dart

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ class CustomTextField extends StatelessWidget {
2323

2424
@override
2525
Widget build(BuildContext context) {
26+
final isDark = Theme.of(context).brightness == Brightness.dark;
27+
2628
return Padding(
2729
padding: const EdgeInsets.only(bottom: 16),
2830
child: Column(
@@ -35,7 +37,10 @@ class CustomTextField extends StatelessWidget {
3537
style: TextStyle(
3638
fontSize: 14,
3739
fontWeight: FontWeight.bold,
38-
color: Theme.of(context).colorScheme.onSurface.withOpacity(0.6),
40+
color: Theme.of(context)
41+
.colorScheme
42+
.onSurfaceVariant
43+
.withValues(alpha: isDark ? 0.9 : 0.8),
3944
letterSpacing: 1,
4045
),
4146
),
@@ -51,18 +56,21 @@ class CustomTextField extends StatelessWidget {
5156
decoration: InputDecoration(
5257
hintText: hint,
5358
hintStyle: TextStyle(
54-
color: Theme.of(context).colorScheme.onSurface.withOpacity(0.3),
59+
color: Theme.of(context)
60+
.colorScheme
61+
.onSurfaceVariant
62+
.withValues(alpha: 0.65),
5563
fontWeight: FontWeight.w400,
5664
fontSize: 16,
5765
),
5866
filled: true,
59-
fillColor: Theme.of(context).colorScheme.surface,
67+
fillColor: isDark ? const Color(0xFF344765) : Theme.of(context).colorScheme.surface,
6068
prefixIcon: Icon(icon, color: Theme.of(context).colorScheme.primary),
6169
suffixIcon: isPassword
6270
? IconButton(
6371
icon: Icon(
6472
obscureText ? Icons.visibility_off : Icons.visibility,
65-
color: Colors.grey,
73+
color: Theme.of(context).colorScheme.onSurfaceVariant,
6674
),
6775
onPressed: onToggleVisibility,
6876
)
@@ -72,18 +80,22 @@ class CustomTextField extends StatelessWidget {
7280
horizontal: 16,
7381
),
7482
border: OutlineInputBorder(
75-
borderRadius: BorderRadius.circular(16),
83+
borderRadius: BorderRadius.circular(24),
7684
borderSide: BorderSide.none,
7785
),
7886
enabledBorder: OutlineInputBorder(
79-
borderRadius: BorderRadius.circular(16),
80-
borderSide: BorderSide(color: Theme.of(context).colorScheme.outline),
87+
borderRadius: BorderRadius.circular(24),
88+
borderSide: BorderSide(
89+
color: isDark
90+
? const Color(0xFF4A5F80)
91+
: Theme.of(context).colorScheme.outline,
92+
),
8193
),
8294
focusedBorder: OutlineInputBorder(
83-
borderRadius: BorderRadius.circular(16),
95+
borderRadius: BorderRadius.circular(24),
8496
borderSide: BorderSide(
8597
color: Theme.of(context).colorScheme.primary,
86-
width: 2,
98+
width: 1.5,
8799
),
88100
),
89101
),

src/lib/features/auth/presentation/view/forgot_password_view.dart

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ class _ForgotPasswordViewState extends State<ForgotPasswordView> {
1515

1616
@override
1717
Widget build(BuildContext context) {
18+
final isDark = Theme.of(context).brightness == Brightness.dark;
19+
1820
return AnimatedBuilder(
1921
animation: _vm,
2022
builder: (context, _) => AuthLayoutTemplate(
@@ -26,9 +28,16 @@ class _ForgotPasswordViewState extends State<ForgotPasswordView> {
2628
customHeaderIcon: Container(
2729
width: 120, height: 120,
2830
decoration: BoxDecoration(
29-
color: Theme.of(context).colorScheme.surface,
31+
color: isDark ? const Color(0xFF1B2A46) : Theme.of(context).colorScheme.surface,
3032
shape: BoxShape.circle,
31-
boxShadow: const [BoxShadow(color: Color(0xFFD1D9E6), blurRadius: 16)],
33+
boxShadow: [
34+
BoxShadow(
35+
color: isDark
36+
? Theme.of(context).colorScheme.primary.withValues(alpha: 0.22)
37+
: const Color(0xFFD1D9E6),
38+
blurRadius: 24,
39+
)
40+
],
3241
),
3342
child: Icon(
3443
Icons.lock_reset,
@@ -63,25 +72,33 @@ class _ForgotPasswordViewState extends State<ForgotPasswordView> {
6372
controller: _vm.emailCtrl,
6473
),
6574
footerContent: Padding(
66-
padding: EdgeInsets.only(bottom: 24.0),
67-
child: Row(
68-
mainAxisAlignment: MainAxisAlignment.center,
69-
children: [
70-
Icon(
71-
Icons.help,
72-
size: 16,
73-
color: Theme.of(context).colorScheme.primary,
74-
),
75-
const SizedBox(width: 4),
76-
Text(
77-
'Cần hỗ trợ? Liên hệ CSKH',
78-
style: TextStyle(
79-
color: Theme.of(context).colorScheme.onSurfaceVariant,
80-
fontSize: 14,
81-
fontWeight: FontWeight.bold,
75+
padding: const EdgeInsets.only(bottom: 24.0),
76+
child: Container(
77+
padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 12),
78+
decoration: BoxDecoration(
79+
color: isDark ? const Color(0xFF111E37) : Theme.of(context).colorScheme.surface,
80+
borderRadius: BorderRadius.circular(999),
81+
border: Border.all(color: Theme.of(context).colorScheme.outline),
82+
),
83+
child: Row(
84+
mainAxisSize: MainAxisSize.min,
85+
children: [
86+
Icon(
87+
Icons.help,
88+
size: 16,
89+
color: Theme.of(context).colorScheme.primary,
8290
),
83-
),
84-
],
91+
const SizedBox(width: 8),
92+
Text(
93+
'Cần hỗ trợ? Liên hệ CSKH',
94+
style: TextStyle(
95+
color: Theme.of(context).colorScheme.onSurfaceVariant,
96+
fontSize: 14,
97+
fontWeight: FontWeight.bold,
98+
),
99+
),
100+
],
101+
),
85102
),
86103
),
87104
),

src/lib/features/auth/presentation/view/new_password_view.dart

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ class _NewPasswordViewState extends State<NewPasswordView> {
1515

1616
@override
1717
Widget build(BuildContext context) {
18+
final isDark = Theme.of(context).brightness == Brightness.dark;
19+
1820
return AnimatedBuilder(
1921
animation: _vm,
2022
builder: (context, _) => AuthLayoutTemplate(
@@ -24,7 +26,7 @@ class _NewPasswordViewState extends State<NewPasswordView> {
2426
isLoading: _vm.isLoading,
2527
customHeaderIcon: CircleAvatar(
2628
radius: 40,
27-
backgroundColor: Color(0xFFEBF2FF),
29+
backgroundColor: isDark ? const Color(0xFF213A63) : const Color(0xFFEBF2FF),
2830
child: Icon(
2931
Icons.lock_reset,
3032
size: 40,
@@ -72,8 +74,13 @@ class _NewPasswordViewState extends State<NewPasswordView> {
7274
Container(
7375
padding: const EdgeInsets.all(12),
7476
decoration: BoxDecoration(
75-
color: const Color(0xFFEBF2FF),
77+
color: isDark
78+
? const Color(0xFF223A63)
79+
: const Color(0xFFEBF2FF),
7680
borderRadius: BorderRadius.circular(12),
81+
border: isDark
82+
? Border.all(color: Theme.of(context).colorScheme.primary.withValues(alpha: 0.25))
83+
: null,
7784
),
7885
child: Row(
7986
children: [

0 commit comments

Comments
 (0)