1
0
forked from baron/baron-sso

회원가입 UI 일관성 및 가시성 수정

This commit is contained in:
2026-05-22 16:03:25 +09:00
parent cb8c7d78c3
commit 4ca492b31c

View File

@@ -16,12 +16,6 @@ class SignupScreen extends StatefulWidget {
}
class _SignupScreenState extends State<SignupScreen> {
static const _signupInk = Color(0xFF111827);
static const _signupBorder = Color(0xFFE5E7EB);
static const _signupSurface = Color(0xFFF8FAFC);
static const _signupMuted = Color(0xFF6B7280);
static const _signupDone = Color(0xFF0F766E);
static const _signupDoneSurface = Color(0xFFECFDF5);
static const _agreementDesktopBreakpoint = 1024.0;
static const _agreementCardMaxWidth = 880.0;
static const _stepIndicatorDesktopBreakpoint = 1024.0;
@@ -69,6 +63,64 @@ class _SignupScreenState extends State<SignupScreen> {
Timer? _phoneTimer;
int _phoneSeconds = 0;
ColorScheme get _scheme => Theme.of(context).colorScheme;
bool get _isDark => _scheme.brightness == Brightness.dark;
Color get _signupInk => _scheme.onSurface;
Color get _signupBorder => _scheme.outlineVariant;
Color get _signupSurface => _scheme.surfaceContainerLow;
Color get _signupCard => _scheme.surface;
Color get _signupMuted => _scheme.onSurfaceVariant;
Color get _signupDone => _signupAccent.withValues(alpha: _isDark ? 0.78 : 0.72);
Color get _signupDoneSurface =>
_signupAccent.withValues(alpha: _isDark ? 0.18 : 0.12);
Color get _signupAccent =>
_isDark ? const Color(0xFF93C5FD) : const Color(0xFF1E3A8A);
Color get _signupOnAccent =>
_isDark ? const Color(0xFF082F49) : Colors.white;
Color get _signupAccentSurface =>
_isDark ? const Color(0xFF172554) : const Color(0xFFDBEAFE);
Color get _signupAccentInk =>
_isDark ? const Color(0xFFBFDBFE) : const Color(0xFF1D4ED8);
Color get _signupRequiredSurface =>
_isDark ? const Color(0xFF312E81) : const Color(0xFFEEF2FF);
Color get _signupRequiredBorder =>
_isDark ? const Color(0xFF4F46E5) : const Color(0xFFC7D2FE);
Color get _signupRequiredInk =>
_isDark ? const Color(0xFFC7D2FE) : const Color(0xFF3730A3);
Color get _signupSummaryBorder =>
_signupAccent.withValues(alpha: _isDark ? 0.28 : 0.16);
BorderSide get _signupDividerSide => BorderSide(color: _signupBorder);
CheckboxThemeData get _signupCheckboxTheme => CheckboxThemeData(
side: _signupDividerSide,
fillColor: WidgetStateProperty.resolveWith((states) {
if (states.contains(WidgetState.selected)) {
return _signupAccent;
}
return _signupCard;
}),
checkColor: WidgetStateProperty.all(_signupOnAccent),
);
ButtonStyle get _signupPrimaryButtonStyle => FilledButton.styleFrom(
minimumSize: const Size.fromHeight(55),
backgroundColor: _signupAccent,
foregroundColor: _signupOnAccent,
disabledBackgroundColor: _isDark
? _scheme.surfaceContainerHighest
: const Color(0xFFE5E7EB),
disabledForegroundColor: _isDark
? _scheme.onSurfaceVariant
: const Color(0xFF9CA3AF),
);
ButtonStyle get _signupSecondaryButtonStyle => OutlinedButton.styleFrom(
minimumSize: const Size.fromHeight(55),
foregroundColor: _signupInk,
side: BorderSide(color: _signupBorder),
);
String _renderTranslatedText(
String key, {
String? fallback,
@@ -454,7 +506,7 @@ class _SignupScreenState extends State<SignupScreen> {
final circleRadius = isDesktop ? 17.0 : 12.0;
final labelStyle = TextStyle(
fontSize: isDesktop ? 12 : 9,
color: isCurrent ? _signupInk : (isDone ? _signupDone : _signupMuted),
color: isCurrent ? _signupAccent : (isDone ? _signupDone : _signupMuted),
fontWeight: isCurrent || isDone ? FontWeight.w700 : FontWeight.w500,
height: 1.2,
);
@@ -469,13 +521,13 @@ class _SignupScreenState extends State<SignupScreen> {
decoration: BoxDecoration(
color: isDone
? _signupDone
: (isCurrent ? _signupInk : _signupSurface),
: (isCurrent ? _signupAccent : _signupSurface),
shape: BoxShape.circle,
border: Border.all(
color: isDone
? _signupDone
: (isCurrent ? _signupInk : _signupBorder),
width: isCurrent ? 1.5 : 1,
: (isCurrent ? _signupAccent : _signupBorder),
width: isDone ? 0 : (isCurrent ? 1.5 : 1),
),
boxShadow: isDesktop && (isCurrent || isDone)
? const [
@@ -497,7 +549,7 @@ class _SignupScreenState extends State<SignupScreen> {
: Text(
'$step',
style: TextStyle(
color: isCurrent ? Colors.white : _signupMuted,
color: isCurrent ? _signupOnAccent : _signupMuted,
fontSize: isDesktop ? 13 : 10,
fontWeight: FontWeight.w700,
),
@@ -564,9 +616,9 @@ class _SignupScreenState extends State<SignupScreen> {
),
child: DecoratedBox(
decoration: BoxDecoration(
color: Colors.white,
color: _signupCard,
borderRadius: BorderRadius.circular(isDesktop ? 24 : 18),
border: Border.all(color: _signupBorder),
border: Border.all(color: _signupSummaryBorder),
boxShadow: isDesktop
? const [
BoxShadow(
@@ -647,58 +699,60 @@ class _SignupScreenState extends State<SignupScreen> {
decoration: BoxDecoration(
color: _signupSurface,
borderRadius: BorderRadius.circular(16),
border: Border.all(color: _signupBorder),
border: Border.all(color: _signupSummaryBorder),
),
child: Padding(
padding: EdgeInsets.all(isDesktop ? 20 : 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
CheckboxListTile(
title: Text(
tr('ui.userfront.signup.agreement.all'),
style: TextStyle(
fontSize: isDesktop ? 17 : 15,
fontWeight: FontWeight.w700,
color: _signupInk,
),
),
subtitle: Padding(
padding: const EdgeInsets.only(top: 4),
child: Text(
tr('msg.userfront.signup.agreement.all_hint'),
style: const TextStyle(
fontSize: 13,
height: 1.45,
color: _signupMuted,
child: CheckboxTheme(
data: _signupCheckboxTheme,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
CheckboxListTile(
title: Text(
tr('ui.userfront.signup.agreement.all'),
style: TextStyle(
fontSize: isDesktop ? 17 : 15,
fontWeight: FontWeight.w700,
color: _signupInk,
),
),
subtitle: Padding(
padding: const EdgeInsets.only(top: 4),
child: Text(
tr('msg.userfront.signup.agreement.all_hint'),
style: TextStyle(
fontSize: 13,
height: 1.45,
color: _signupMuted,
),
),
),
value: _termsAccepted && _privacyAccepted,
onChanged: (val) {
setState(() {
final next = val ?? false;
_termsAccepted = next;
_privacyAccepted = next;
});
},
contentPadding: EdgeInsets.zero,
controlAffinity: ListTileControlAffinity.leading,
),
value: _termsAccepted && _privacyAccepted,
onChanged: (val) {
setState(() {
final next = val ?? false;
_termsAccepted = next;
_privacyAccepted = next;
});
},
contentPadding: EdgeInsets.zero,
controlAffinity: ListTileControlAffinity.leading,
activeColor: _signupInk,
),
const SizedBox(height: 8),
Text(
tr(
'msg.userfront.signup.agreement.progress',
params: {'count': '$acceptedCount', 'total': '2'},
const SizedBox(height: 8),
Text(
tr(
'msg.userfront.signup.agreement.progress',
params: {'count': '$acceptedCount', 'total': '2'},
),
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
color: _signupMuted,
),
),
style: const TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
color: _signupMuted,
),
),
],
],
),
),
),
);
@@ -716,13 +770,15 @@ class _SignupScreenState extends State<SignupScreen> {
return DecoratedBox(
decoration: BoxDecoration(
color: Colors.white,
color: _signupCard,
borderRadius: BorderRadius.circular(18),
border: Border.all(color: _signupBorder),
border: Border.all(color: _signupSummaryBorder),
),
child: Padding(
padding: EdgeInsets.all(isDesktop ? 20 : 16),
child: Column(
child: CheckboxTheme(
data: _signupCheckboxTheme,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Row(
@@ -742,7 +798,7 @@ class _SignupScreenState extends State<SignupScreen> {
padding: const EdgeInsets.only(top: 6),
child: Text(
summary,
style: const TextStyle(
style: TextStyle(
fontSize: 13,
height: 1.45,
color: _signupMuted,
@@ -753,7 +809,6 @@ class _SignupScreenState extends State<SignupScreen> {
onChanged: onChanged,
controlAffinity: ListTileControlAffinity.leading,
contentPadding: EdgeInsets.zero,
activeColor: _signupInk,
),
),
const SizedBox(width: 12),
@@ -767,7 +822,7 @@ class _SignupScreenState extends State<SignupScreen> {
padding: EdgeInsets.all(isDesktop ? 18 : 14),
decoration: BoxDecoration(
color: _signupSurface,
border: Border.all(color: _signupBorder),
border: Border.all(color: _signupSummaryBorder),
borderRadius: BorderRadius.circular(14),
),
child: SingleChildScrollView(
@@ -782,6 +837,7 @@ class _SignupScreenState extends State<SignupScreen> {
),
),
],
),
),
),
);
@@ -791,16 +847,16 @@ class _SignupScreenState extends State<SignupScreen> {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
decoration: BoxDecoration(
color: const Color(0xFFEEF2FF),
color: _signupRequiredSurface,
borderRadius: BorderRadius.circular(999),
border: Border.all(color: const Color(0xFFC7D2FE)),
border: Border.all(color: _signupRequiredBorder),
),
child: Text(
tr('ui.userfront.signup.agreement.required'),
style: const TextStyle(
style: TextStyle(
fontSize: 11,
fontWeight: FontWeight.w700,
color: Color(0xFF3730A3),
color: _signupRequiredInk,
),
),
);
@@ -1234,7 +1290,7 @@ Matters not expressly provided in this Policy are governed by the Company's inte
),
child: DecoratedBox(
decoration: BoxDecoration(
color: Colors.white,
color: _signupCard,
borderRadius: BorderRadius.circular(isDesktop ? 24 : 18),
border: Border.all(color: _signupBorder),
boxShadow: isDesktop
@@ -1331,7 +1387,7 @@ Matters not expressly provided in this Policy are governed by the Company's inte
Widget _buildAuthNoticeCard({required bool isDesktop}) {
return DecoratedBox(
decoration: BoxDecoration(
color: const Color(0xFFF8FAFC),
color: _signupSurface,
borderRadius: BorderRadius.circular(16),
border: Border.all(color: _signupBorder),
),
@@ -1344,13 +1400,13 @@ Matters not expressly provided in this Policy are governed by the Company's inte
width: isDesktop ? 36 : 32,
height: isDesktop ? 36 : 32,
decoration: BoxDecoration(
color: const Color(0xFFDBEAFE),
color: _signupAccentSurface,
borderRadius: BorderRadius.circular(999),
),
child: const Icon(
child: Icon(
Icons.info_outline,
size: 18,
color: Color(0xFF1D4ED8),
color: _signupAccentInk,
),
),
const SizedBox(width: 12),
@@ -1360,7 +1416,7 @@ Matters not expressly provided in this Policy are governed by the Company's inte
style: TextStyle(
fontSize: isDesktop ? 14 : 12,
height: 1.4,
color: const Color(0xFF1E3A8A),
color: _signupAccent,
fontWeight: FontWeight.w600,
),
),
@@ -1394,9 +1450,9 @@ Matters not expressly provided in this Policy are governed by the Company's inte
}) {
return DecoratedBox(
decoration: BoxDecoration(
color: Colors.white,
color: _signupCard,
borderRadius: BorderRadius.circular(18),
border: Border.all(color: _signupBorder),
border: Border.all(color: _signupSummaryBorder),
),
child: Padding(
padding: EdgeInsets.all(isDesktop ? 20 : 16),
@@ -1457,12 +1513,7 @@ Matters not expressly provided in this Policy are governed by the Company's inte
width: 108,
child: FilledButton(
onPressed: buttonEnabled ? onRequestCode : null,
style: FilledButton.styleFrom(
backgroundColor: _signupInk,
foregroundColor: Colors.white,
disabledBackgroundColor: const Color(0xFFE5E7EB),
disabledForegroundColor: const Color(0xFF9CA3AF),
),
style: _signupPrimaryButtonStyle,
child: Text(
buttonLabel,
style: const TextStyle(
@@ -1497,12 +1548,7 @@ Matters not expressly provided in this Policy are governed by the Company's inte
height: 52,
child: FilledButton(
onPressed: buttonEnabled ? onRequestCode : null,
style: FilledButton.styleFrom(
backgroundColor: _signupInk,
foregroundColor: Colors.white,
disabledBackgroundColor: const Color(0xFFE5E7EB),
disabledForegroundColor: const Color(0xFF9CA3AF),
),
style: _signupPrimaryButtonStyle,
child: Text(
buttonLabel,
style: const TextStyle(
@@ -1592,11 +1638,11 @@ Matters not expressly provided in this Policy are governed by the Company's inte
decoration: BoxDecoration(
color: _signupDoneSurface,
borderRadius: BorderRadius.circular(999),
border: Border.all(color: const Color(0xFFA7F3D0)),
border: Border.all(color: _signupDone.withValues(alpha: 0.35)),
),
child: Text(
text.replaceFirst('', ''),
style: const TextStyle(
style: TextStyle(
fontSize: 11,
fontWeight: FontWeight.w700,
color: _signupDone,
@@ -1611,16 +1657,16 @@ Matters not expressly provided in this Policy are governed by the Company's inte
decoration: BoxDecoration(
color: _signupDoneSurface,
borderRadius: BorderRadius.circular(12),
border: Border.all(color: const Color(0xFFA7F3D0)),
border: Border.all(color: _signupDone.withValues(alpha: 0.35)),
),
child: Row(
children: [
const Icon(Icons.check_circle, size: 18, color: _signupDone),
Icon(Icons.check_circle, size: 18, color: _signupDone),
const SizedBox(width: 8),
Expanded(
child: Text(
text.replaceFirst('', ''),
style: const TextStyle(
style: TextStyle(
color: _signupDone,
fontSize: 13,
fontWeight: FontWeight.w700,
@@ -1647,9 +1693,9 @@ Matters not expressly provided in this Policy are governed by the Company's inte
),
child: DecoratedBox(
decoration: BoxDecoration(
color: Colors.white,
color: _signupCard,
borderRadius: BorderRadius.circular(isDesktop ? 24 : 18),
border: Border.all(color: _signupBorder),
border: Border.all(color: _signupSummaryBorder),
boxShadow: isDesktop
? const [
BoxShadow(
@@ -1820,13 +1866,13 @@ Matters not expressly provided in this Policy are governed by the Company's inte
width: isDesktop ? 36 : 32,
height: isDesktop ? 36 : 32,
decoration: BoxDecoration(
color: const Color(0xFFEEF2FF),
color: _signupAccentSurface,
borderRadius: BorderRadius.circular(999),
),
child: const Icon(
child: Icon(
Icons.badge_outlined,
size: 18,
color: Color(0xFF4338CA),
color: _signupAccentInk,
),
),
const SizedBox(width: 12),
@@ -1836,7 +1882,7 @@ Matters not expressly provided in this Policy are governed by the Company's inte
style: TextStyle(
fontSize: isDesktop ? 14 : 12,
height: 1.4,
color: _signupInk,
color: _signupAccent,
fontWeight: FontWeight.w600,
),
),
@@ -1856,9 +1902,9 @@ Matters not expressly provided in this Policy are governed by the Company's inte
}) {
return DecoratedBox(
decoration: BoxDecoration(
color: Colors.white,
color: _signupCard,
borderRadius: BorderRadius.circular(18),
border: Border.all(color: _signupBorder),
border: Border.all(color: _signupSummaryBorder),
),
child: Padding(
padding: EdgeInsets.all(isDesktop ? 20 : 16),
@@ -1883,7 +1929,7 @@ Matters not expressly provided in this Policy are governed by the Company's inte
const SizedBox(height: 6),
Text(
description,
style: const TextStyle(
style: TextStyle(
fontSize: 13,
height: 1.45,
color: _signupMuted,
@@ -2018,9 +2064,9 @@ Matters not expressly provided in this Policy are governed by the Company's inte
),
child: DecoratedBox(
decoration: BoxDecoration(
color: Colors.white,
color: _signupCard,
borderRadius: BorderRadius.circular(isDesktop ? 24 : 18),
border: Border.all(color: _signupBorder),
border: Border.all(color: _signupSummaryBorder),
boxShadow: isDesktop
? const [
BoxShadow(
@@ -2154,13 +2200,13 @@ Matters not expressly provided in this Policy are governed by the Company's inte
width: isDesktop ? 36 : 32,
height: isDesktop ? 36 : 32,
decoration: BoxDecoration(
color: const Color(0xFFDBEAFE),
color: _signupAccentSurface,
borderRadius: BorderRadius.circular(999),
),
child: const Icon(
child: Icon(
Icons.security_rounded,
size: 18,
color: Color(0xFF1D4ED8),
color: _signupAccentInk,
),
),
const SizedBox(width: 12),
@@ -2170,7 +2216,7 @@ Matters not expressly provided in this Policy are governed by the Company's inte
style: TextStyle(
fontSize: isDesktop ? 14 : 12,
height: 1.4,
color: const Color(0xFF1E3A8A),
color: _signupAccent,
fontWeight: FontWeight.w600,
),
),
@@ -2189,9 +2235,9 @@ Matters not expressly provided in this Policy are governed by the Company's inte
}) {
return DecoratedBox(
decoration: BoxDecoration(
color: Colors.white,
color: _signupCard,
borderRadius: BorderRadius.circular(18),
border: Border.all(color: _signupBorder),
border: Border.all(color: _signupSummaryBorder),
),
child: Padding(
padding: EdgeInsets.all(isDesktop ? 20 : 16),
@@ -2209,7 +2255,7 @@ Matters not expressly provided in this Policy are governed by the Company's inte
const SizedBox(height: 6),
Text(
description,
style: const TextStyle(
style: TextStyle(
fontSize: 13,
height: 1.45,
color: _signupMuted,
@@ -2231,7 +2277,7 @@ Matters not expressly provided in this Policy are governed by the Company's inte
decoration: BoxDecoration(
color: _signupSurface,
borderRadius: BorderRadius.circular(14),
border: Border.all(color: _signupBorder),
border: Border.all(color: _signupSummaryBorder),
),
child: Padding(
padding: EdgeInsets.all(isDesktop ? 16 : 14),
@@ -2283,15 +2329,17 @@ Matters not expressly provided in this Policy are governed by the Company's inte
}
return Scaffold(
backgroundColor: Colors.white,
backgroundColor: _scheme.surfaceContainerLowest,
appBar: AppBar(
title: Text(
tr('ui.userfront.signup.title'),
style: const TextStyle(fontWeight: FontWeight.bold),
),
elevation: 0,
backgroundColor: Colors.white,
foregroundColor: Colors.black,
backgroundColor: _signupCard,
foregroundColor: _signupInk,
surfaceTintColor: Colors.transparent,
shape: Border(bottom: _signupDividerSide),
),
body: SafeArea(
child: Column(
@@ -2309,14 +2357,8 @@ Matters not expressly provided in this Policy are governed by the Company's inte
Expanded(
child: OutlinedButton(
onPressed: () => setState(() => _currentStep--),
style: OutlinedButton.styleFrom(
minimumSize: const Size.fromHeight(55),
side: const BorderSide(color: Colors.black),
),
child: Text(
tr('ui.common.prev'),
style: const TextStyle(color: Colors.black),
),
style: _signupSecondaryButtonStyle,
child: Text(tr('ui.common.prev')),
),
),
const SizedBox(width: 12),
@@ -2328,16 +2370,13 @@ Matters not expressly provided in this Policy are governed by the Company's inte
? () => setState(() => _currentStep++)
: null)
: (_isLoading ? null : _handleSignup),
style: FilledButton.styleFrom(
minimumSize: const Size.fromHeight(55),
backgroundColor: Colors.black,
),
style: _signupPrimaryButtonStyle,
child: _isLoading
? const SizedBox(
? SizedBox(
height: 20,
width: 20,
child: CircularProgressIndicator(
color: Colors.white,
color: _scheme.onPrimary,
strokeWidth: 2,
),
)