Enhance login page with new UI and styling updates

Introduced a redesigned login page featuring a two-column layout with a branding section. Added new styles such as gradient backgrounds, input fields with focus animations, and button hover effects. These changes improve the visual appeal and user experience.
This commit is contained in:
2026-02-12 10:24:50 +01:00
parent 7b011326a6
commit 672473603e
2 changed files with 156 additions and 22 deletions

View File

@@ -26,9 +26,20 @@ export function LoginPage() {
return ( return (
<div className="login-wrap"> <div className="login-wrap">
<div className="login-shell">
<section className="login-brand card">
<h1>NexaPG Monitor</h1>
<p>PostgreSQL Monitoring, Query Insights und Infrastruktur-Overview in einer Ansicht.</p>
<div className="login-brand-points">
<span>Multi-Target Monitoring</span>
<span>Live Database Overview</span>
<span>RBAC + Audit Logging</span>
</div>
</section>
<form className="card login-card" onSubmit={submit}> <form className="card login-card" onSubmit={submit}>
<h2>Login</h2> <h2>Login</h2>
<label>Email</label> <label>Email</label>
<div className="input-shell">
<input <input
type="email" type="email"
placeholder="E-Mail" placeholder="E-Mail"
@@ -36,7 +47,9 @@ export function LoginPage() {
onChange={(e) => setEmail(e.target.value)} onChange={(e) => setEmail(e.target.value)}
autoComplete="username" autoComplete="username"
/> />
</div>
<label>Passwort</label> <label>Passwort</label>
<div className="input-shell">
<input <input
type="password" type="password"
placeholder="Password" placeholder="Password"
@@ -44,9 +57,11 @@ export function LoginPage() {
onChange={(e) => setPassword(e.target.value)} onChange={(e) => setPassword(e.target.value)}
autoComplete="current-password" autoComplete="current-password"
/> />
</div>
{error && <p className="error">{error}</p>} {error && <p className="error">{error}</p>}
<button disabled={loading}>{loading ? "Bitte warten..." : "Einloggen"}</button> <button className="login-cta" disabled={loading}>{loading ? "Bitte warten..." : "Einloggen"}</button>
</form> </form>
</div> </div>
</div>
); );
} }

View File

@@ -213,14 +213,127 @@ td {
min-height: 100vh; min-height: 100vh;
display: grid; display: grid;
place-items: center; place-items: center;
padding: 20px;
background:
radial-gradient(1000px 500px at 10% 10%, #12366e55, transparent),
radial-gradient(900px 450px at 90% 90%, #1e4f7e40, transparent);
} }
.login-card { .login-card {
width: min(420px, 90vw); width: min(460px, 92vw);
display: grid;
gap: 10px;
border-color: #3559a3;
backdrop-filter: blur(8px);
animation: loginEnter 0.5s ease;
}
.login-shell {
width: min(1120px, 96vw);
display: grid;
grid-template-columns: 1.1fr 0.9fr;
gap: 18px;
}
.login-brand {
min-height: 420px;
display: grid;
align-content: center;
gap: 14px;
border-color: #27498d;
background:
linear-gradient(155deg, #152957 0%, #102147 40%, #0f1b3d 100%);
}
.login-brand h1 {
margin: 0;
font-size: 38px;
}
.login-brand p {
margin: 0;
color: #b5c5e4;
max-width: 58ch;
}
.login-brand-points {
display: grid; display: grid;
gap: 8px; gap: 8px;
} }
.login-brand-points span {
color: #d2e0f8;
font-size: 14px;
}
.input-shell {
position: relative;
border: 1px solid #2b3f74;
border-radius: 12px;
padding: 1px;
background: #0e1731;
transition: border-color 0.2s ease;
}
.input-shell::before {
content: "";
position: absolute;
inset: -1px;
border-radius: 12px;
padding: 1px;
background: conic-gradient(#38bdf8, #4f6ee7, #38bdf8);
-webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
-webkit-mask-composite: xor;
mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
mask-composite: exclude;
opacity: 0;
}
.input-shell:focus-within {
border-color: transparent;
}
.input-shell:focus-within::before {
opacity: 1;
animation: spin 1.2s linear infinite;
}
.input-shell input {
width: 100%;
border: 0;
outline: none;
background: transparent;
}
.login-cta {
margin-top: 2px;
font-weight: 700;
border-color: #3f74d6;
background: linear-gradient(90deg, #1e74d6, #1b5ab6);
}
.login-cta:hover {
border-color: #6aa8ff;
filter: brightness(1.05);
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
@keyframes loginEnter {
from {
opacity: 0;
transform: translateY(8px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.query { .query {
max-width: 400px; max-width: 400px;
white-space: nowrap; white-space: nowrap;
@@ -298,4 +411,10 @@ td {
height: auto; height: auto;
overflow: visible; overflow: visible;
} }
.login-shell {
grid-template-columns: 1fr;
}
.login-brand {
min-height: 240px;
}
} }