Новый стиль

This commit is contained in:
Халимов Рустам
2026-03-31 21:11:05 +03:00
parent 4faa7561a0
commit aa69c44a64
39 changed files with 3812 additions and 735 deletions
@@ -39,10 +39,10 @@ export default function RegisterForm({ onLoginClick, enableRegistration }: Props
<AnimatePresence>
{error && (
<motion.div
initial={{ opacity: 0, y: -10 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -10 }}
className="mb-6 p-3.5 rounded-xl bg-red-500/10 border border-red-500/20 text-red-400 text-sm font-medium text-center"
initial={{ opacity: 0, scale: 0.98 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.98 }}
className="mb-8 p-4 rounded-2xl bg-error/10 border-none text-error text-[13px] font-bold text-center uppercase tracking-widest"
role="alert"
>
{error}
@@ -51,46 +51,53 @@ export default function RegisterForm({ onLoginClick, enableRegistration }: Props
</AnimatePresence>
<form onSubmit={handleSubmit} className="space-y-4" autoComplete="off">
<div>
<label className="block text-sm font-semibold text-zinc-300 mb-2">
Username <span className="text-zinc-600 font-normal ml-1">({lang === 'ru' ? 'латиница, нельзя изменить' : 'latin, cannot change'})</span>
<div className="knot-input-group">
<label className="block text-[11px] font-black uppercase tracking-[0.2em] text-on-surface-variant/40 mb-3 ml-1">
{lang === 'ru' ? 'Имя пользователя (латиница)' : 'Username (latin only)'}
</label>
<input
type="text"
value={credentials.username}
onChange={(e) => setCredentials({ ...credentials, username: e.target.value.replace(/[^a-zA-Z0-9_]/g, '') })}
placeholder="username"
className="w-full px-4 py-3.5 rounded-xl bg-[#18181b] border border-white/5 text-white placeholder-zinc-600 focus:border-[#9b66ff]/50 focus:bg-[#1f1f22] transition-colors outline-none text-[15px]"
required
autoFocus
autoComplete="off"
/>
<div className="relative">
<span className="material-symbols-outlined absolute left-4 top-1/2 -translate-y-1/2 text-on-surface-variant/40 text-[20px]">alternate_email</span>
<input
type="text"
value={credentials.username}
onChange={(e) => setCredentials({ ...credentials, username: e.target.value.replace(/[^a-zA-Z0-9_]/g, '') })}
placeholder="username"
className="w-full pl-12 pr-4 py-4 rounded-2xl bg-surface-container-highest/60 text-on-surface placeholder-on-surface-variant/20 border-none focus:ring-2 focus:ring-primary/20 transition-all outline-none text-[15px]"
required
autoFocus
autoComplete="off"
/>
</div>
</div>
<div>
<label className="block text-sm font-semibold text-zinc-300 mb-2">
<div className="knot-input-group">
<label className="block text-[11px] font-black uppercase tracking-[0.2em] text-on-surface-variant/40 mb-3 ml-1">
{lang === 'ru' ? 'Отображаемое имя' : 'Display Name'}
</label>
<input
type="text"
value={credentials.displayName}
onChange={(e) => setCredentials({ ...credentials, displayName: e.target.value })}
placeholder={lang === 'ru' ? 'Ваше имя (любой язык)' : 'Your name'}
className="w-full px-4 py-3.5 rounded-xl bg-[#18181b] border border-white/5 text-white placeholder-zinc-600 focus:border-[#9b66ff]/50 focus:bg-[#1f1f22] transition-colors outline-none text-[15px]"
/>
<div className="relative">
<span className="material-symbols-outlined absolute left-4 top-1/2 -translate-y-1/2 text-on-surface-variant/40 text-[20px]">face</span>
<input
type="text"
value={credentials.displayName}
onChange={(e) => setCredentials({ ...credentials, displayName: e.target.value })}
placeholder={lang === 'ru' ? 'Ваше имя' : 'Your name'}
className="w-full pl-12 pr-4 py-4 rounded-2xl bg-surface-container-highest/60 text-on-surface placeholder-on-surface-variant/20 border-none focus:ring-2 focus:ring-primary/20 transition-all outline-none text-[15px]"
/>
</div>
</div>
<div>
<label className="block text-sm font-semibold text-zinc-300 mb-2">
<div className="knot-input-group">
<label className="block text-[11px] font-black uppercase tracking-[0.2em] text-on-surface-variant/40 mb-3 ml-1">
{lang === 'ru' ? 'Пароль' : 'Password'}
</label>
<div className="relative">
<span className="material-symbols-outlined absolute left-4 top-1/2 -translate-y-1/2 text-on-surface-variant/40 text-[20px]">lock_open</span>
<input
type={showPassword ? 'text' : 'password'}
value={credentials.password}
onChange={(e) => setCredentials({ ...credentials, password: e.target.value })}
placeholder={lang === 'ru' ? 'Введите пароль' : 'Enter password'}
className="w-full px-4 py-3.5 rounded-xl bg-[#18181b] border border-white/5 text-white placeholder-zinc-600 focus:border-[#9b66ff]/50 focus:bg-[#1f1f22] transition-colors pr-12 outline-none text-[15px]"
placeholder="••••••••"
className="w-full pl-12 pr-12 py-4 rounded-2xl bg-surface-container-highest/60 text-on-surface placeholder-on-surface-variant/20 border-none focus:ring-2 focus:ring-primary/20 transition-all outline-none text-[15px]"
required
autoComplete="new-password"
minLength={8}
@@ -98,14 +105,14 @@ export default function RegisterForm({ onLoginClick, enableRegistration }: Props
<button
type="button"
onClick={() => setShowPassword(!showPassword)}
className="absolute right-4 top-1/2 -translate-y-1/2 text-zinc-500 hover:text-zinc-300 transition-colors"
className="absolute right-4 top-1/2 -translate-y-1/2 text-on-surface-variant/40 hover:text-primary transition-colors slide-on-ice"
>
{showPassword ? <EyeOff size={18} /> : <Eye size={18} />}
<span className="material-symbols-outlined text-[20px]">{showPassword ? 'visibility_off' : 'visibility'}</span>
</button>
</div>
<p className="mt-2 text-[12px] text-zinc-500 flex items-center gap-1.5 font-medium">
<span className="w-1 h-1 rounded-full bg-[#9b66ff]" />
{lang === 'ru' ? 'Минимум 8 символов, буквы и цифры' : 'Minimum 8 characters, letters and numbers'}
<p className="mt-3 text-[10px] text-on-surface-variant/40 flex items-center gap-1.5 font-black uppercase tracking-widest ml-1">
<span className="w-2.5 h-2.5 rounded-full border-2 border-primary" />
{lang === 'ru' ? '8+ символов, любые знаки' : '8+ characters required'}
</p>
</div>
@@ -122,36 +129,35 @@ export default function RegisterForm({ onLoginClick, enableRegistration }: Props
/>
</div>
<motion.button
whileHover={{ scale: 1.01 }}
whileTap={{ scale: 0.99 }}
<button
disabled={isSubmitting}
type="submit"
className="w-full py-3.5 px-4 rounded-xl bg-[#8b5cf6] hover:bg-[#7c3aed] text-white font-semibold flex items-center justify-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed mt-8 transition-colors text-[16px]"
style={{ marginTop: '32px' }}
className="knot-button-primary w-full py-4 mt-8 flex items-center justify-center gap-3 disabled:opacity-50 slide-on-ice"
>
{isSubmitting ? (
<div className="w-5 h-5 border-2 border-white/30 border-t-white rounded-full animate-spin" />
<div className="w-5 h-5 border-2 border-on-primary/30 border-t-on-primary rounded-full animate-spin" />
) : (
<>
{lang === 'ru' ? 'Создать аккаунт' : 'Create account'}
<ArrowRight size={18} />
<span className="font-black uppercase tracking-widest text-[14px]">
{lang === 'ru' ? 'Создать аккаунт' : 'Create Account'}
</span>
<span className="material-symbols-outlined text-[20px]">check_circle</span>
</>
)}
</motion.button>
</button>
</form>
{enableRegistration && (
<div className="mt-8 pt-6 border-t border-white/5 flex justify-center items-center gap-2">
<p className="text-zinc-500 text-[13px] font-medium">
<div className="mt-10 pt-8 border-t border-on-surface-variant/5 flex flex-col items-center gap-4">
<p className="text-on-surface-variant/40 text-[11px] font-black uppercase tracking-widest">
{lang === 'ru' ? 'Уже есть аккаунт?' : 'Already have an account?'}
</p>
<button
onClick={onLoginClick}
className="text-[#7c3aed] hover:text-[#8b5cf6] text-[13px] font-semibold transition-colors"
className="text-primary hover:text-primary/80 text-[13px] font-black uppercase tracking-widest transition-all slide-on-ice"
type="button"
>
{lang === 'ru' ? 'Войти' : 'Login'}
{lang === 'ru' ? 'Войти в систему' : 'Sign In instead'}
</button>
</div>
)}