From 47df3a78dc2d75a26bf018efc2f7738fcc36d4c8 Mon Sep 17 00:00:00 2001 From: Liutenko Oleksandr Date: Fri, 25 Sep 2026 15:21:11 +0300 Subject: [PATCH] Redesign login page (#5) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Rename header to "Assistant System", subtitle to "Вхід у систему" - Glassmorphism card over animated gradient backdrop, logo mark - Password visibility toggle, larger inputs, focus rings Co-Authored-By: Claude Opus 5.5 --- frontend/src/features/auth/LoginPage.css | 235 ++++++++++++++++++++--- frontend/src/features/auth/LoginPage.tsx | 52 +++-- 2 files changed, 247 insertions(+), 40 deletions(-) diff --git a/frontend/src/features/auth/LoginPage.css b/frontend/src/features/auth/LoginPage.css index 58cc62a..23b51e0 100644 --- a/frontend/src/features/auth/LoginPage.css +++ b/frontend/src/features/auth/LoginPage.css @@ -1,68 +1,230 @@ .login-page { + --login-accent: #7c3aed; + --login-glass: rgba(255, 255, 255, 0.72); + --login-glass-border: rgba(255, 255, 255, 0.6); + --login-input-bg: rgba(255, 255, 255, 0.85); + + position: relative; min-height: 100svh; display: flex; align-items: center; justify-content: center; - padding: 24px; + padding: 24px 16px; + overflow: hidden; + isolation: isolate; + background: + radial-gradient(1200px 600px at 10% -10%, rgba(37, 99, 235, 0.14), transparent 60%), + radial-gradient(900px 500px at 110% 110%, rgba(124, 58, 237, 0.14), transparent 60%), + var(--color-bg); +} + +@media (prefers-color-scheme: dark) { + .login-page { + --login-accent: #a78bfa; + --login-glass: rgba(23, 26, 33, 0.7); + --login-glass-border: rgba(255, 255, 255, 0.08); + --login-input-bg: rgba(15, 17, 21, 0.7); + } +} + +/* Декоративные размытые пятна на фоне */ +.login-backdrop { + position: absolute; + inset: 0; + z-index: -1; + pointer-events: none; +} + +.login-blob { + position: absolute; + border-radius: 50%; + filter: blur(70px); + opacity: 0.55; + animation: login-float 18s ease-in-out infinite alternate; +} + +.login-blob--a { + width: 380px; + height: 380px; + top: -80px; + left: -60px; + background: var(--color-primary); +} + +.login-blob--b { + width: 320px; + height: 320px; + bottom: -90px; + right: -40px; + background: var(--login-accent); + animation-delay: -6s; +} + +.login-blob--c { + width: 220px; + height: 220px; + top: 55%; + left: 60%; + background: #06b6d4; + opacity: 0.3; + animation-delay: -12s; +} + +@keyframes login-float { + from { + transform: translate3d(0, 0, 0) scale(1); + } + to { + transform: translate3d(40px, 30px, 0) scale(1.1); + } +} + +@media (prefers-reduced-motion: reduce) { + .login-blob { + animation: none; + } } .login-card { width: 100%; - max-width: 380px; - background: var(--color-surface); - border: 1px solid var(--color-border); - border-radius: 12px; - box-shadow: var(--shadow-card); - padding: 32px; + max-width: 400px; + background: var(--login-glass); + border: 1px solid var(--login-glass-border); + border-radius: 20px; + box-shadow: + 0 20px 50px -12px rgba(16, 24, 40, 0.25), + 0 1px 2px rgba(16, 24, 40, 0.06); + backdrop-filter: blur(18px) saturate(140%); + -webkit-backdrop-filter: blur(18px) saturate(140%); + padding: 40px 32px 32px; + animation: login-enter 0.45s cubic-bezier(0.2, 0.8, 0.2, 1) both; +} + +@keyframes login-enter { + from { + opacity: 0; + transform: translateY(12px) scale(0.98); + } +} + +@media (max-width: 420px) { + .login-card { + padding: 32px 20px 24px; + border-radius: 16px; + } } .login-header { - margin-bottom: 24px; + margin-bottom: 28px; text-align: center; } +.login-logo { + width: 56px; + height: 56px; + margin: 0 auto 16px; + display: grid; + place-items: center; + border-radius: 16px; + color: #fff; + background: linear-gradient(135deg, var(--color-primary), var(--login-accent)); + box-shadow: 0 10px 24px -8px var(--color-primary); +} + .login-header h1 { - font-size: 22px; - margin-bottom: 4px; + font-size: 26px; + font-weight: 700; + letter-spacing: -0.02em; + margin-bottom: 6px; + background: linear-gradient(135deg, var(--color-text) 30%, var(--color-primary)); + -webkit-background-clip: text; + background-clip: text; + color: transparent; } .login-header p { color: var(--color-text-muted); - font-size: 14px; + font-size: 15px; } .login-field { - margin-bottom: 16px; + margin-bottom: 18px; } .login-field label { display: block; font-size: 13px; - font-weight: 500; - margin-bottom: 6px; + font-weight: 600; + margin-bottom: 8px; color: var(--color-text); } .login-field input { width: 100%; - padding: 10px 12px; + height: 46px; + padding: 0 14px; border: 1px solid var(--color-border); - border-radius: 8px; - background: var(--color-bg); + border-radius: 12px; + background: var(--login-input-bg); color: var(--color-text); - font-size: 14px; + font-size: 15px; outline: none; - transition: border-color 0.15s ease; + transition: + border-color 0.15s ease, + box-shadow 0.15s ease; +} + +.login-field input::placeholder { + color: var(--color-text-muted); + opacity: 0.7; } .login-field input:focus { border-color: var(--color-primary); + box-shadow: 0 0 0 4px color-mix(in srgb, var(--color-primary) 18%, transparent); } .login-field input:disabled { opacity: 0.6; } +.login-password { + position: relative; +} + +.login-password input { + padding-right: 46px; +} + +.login-toggle { + position: absolute; + top: 50%; + right: 6px; + transform: translateY(-50%); + width: 34px; + height: 34px; + display: grid; + place-items: center; + border: none; + border-radius: 8px; + background: transparent; + color: var(--color-text-muted); + cursor: pointer; + transition: + color 0.15s ease, + background-color 0.15s ease; +} + +.login-toggle:hover { + color: var(--color-text); + background: color-mix(in srgb, var(--color-text) 8%, transparent); +} + +.login-toggle:focus-visible { + outline: 2px solid var(--color-primary); + outline-offset: 1px; +} + .login-error { display: flex; gap: 8px; @@ -70,23 +232,29 @@ background: var(--color-danger-bg); border: 1px solid var(--color-danger-border); color: var(--color-danger); - border-radius: 8px; - padding: 10px 12px; + border-radius: 12px; + padding: 10px 14px; font-size: 13px; - margin-bottom: 16px; + margin-bottom: 18px; } .login-submit { width: 100%; - padding: 11px 16px; + height: 48px; + margin-top: 8px; + padding: 0 16px; border: none; - border-radius: 8px; - background: var(--color-primary); + border-radius: 12px; + background: linear-gradient(135deg, var(--color-primary), var(--login-accent)); color: #fff; - font-size: 14px; + font-size: 15px; font-weight: 600; cursor: pointer; - transition: background-color 0.15s ease; + box-shadow: 0 10px 24px -10px var(--color-primary); + transition: + transform 0.15s ease, + box-shadow 0.15s ease, + filter 0.15s ease; display: flex; align-items: center; justify-content: center; @@ -94,7 +262,18 @@ } .login-submit:hover:not(:disabled) { - background: var(--color-primary-hover); + transform: translateY(-1px); + filter: brightness(1.06); + box-shadow: 0 14px 28px -10px var(--color-primary); +} + +.login-submit:active:not(:disabled) { + transform: translateY(0); +} + +.login-submit:focus-visible { + outline: 2px solid var(--color-primary); + outline-offset: 2px; } .login-submit:disabled { diff --git a/frontend/src/features/auth/LoginPage.tsx b/frontend/src/features/auth/LoginPage.tsx index c058bec..c6bd175 100644 --- a/frontend/src/features/auth/LoginPage.tsx +++ b/frontend/src/features/auth/LoginPage.tsx @@ -19,6 +19,7 @@ export function LoginPage() { const [email, setEmail] = useState('') const [password, setPassword] = useState('') + const [showPassword, setShowPassword] = useState(false) const [submitting, setSubmitting] = useState(false) const [formError, setFormError] = useState(null) @@ -45,10 +46,22 @@ export function LoginPage() { return (
+ +
-

lux_fiscal

-

Вход в систему фискализации заказов

+ +

Assistant System

+

Вхід у систему

@@ -74,16 +87,31 @@ export function LoginPage() {
- setPassword(e.target.value)} - placeholder="••••••••" - /> +
+ setPassword(e.target.value)} + placeholder="••••••••" + /> + +