l0qp1n5qr: Restyle the sign-in screen to the redesign spec
This commit is contained in:
@@ -6,6 +6,7 @@ import "./globals.css";
|
||||
import "../styles/type.css";
|
||||
import "../styles/buttons.css";
|
||||
import "../styles/avatar.css";
|
||||
import "../styles/signin.css";
|
||||
import "../styles/legacy.css";
|
||||
|
||||
const manrope = Manrope({
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { useState, type FormEvent } from "react";
|
||||
import { signIn, type Person } from "@/lib/auth-client";
|
||||
import { Logo } from "./Logo";
|
||||
import { SparkleButton } from "./Buttons";
|
||||
|
||||
export function SignInForm({ onSignedIn }: { onSignedIn: (p: Person) => void }) {
|
||||
const [email, setEmail] = useState("");
|
||||
@@ -27,39 +28,72 @@ export function SignInForm({ onSignedIn }: { onSignedIn: (p: Person) => void })
|
||||
}
|
||||
|
||||
return (
|
||||
<main className="center">
|
||||
<form className="card" onSubmit={submit} noValidate>
|
||||
<Logo />
|
||||
<h1>Sign in to Minnect</h1>
|
||||
<main className="signin">
|
||||
<div className="signin-glow" aria-hidden="true" />
|
||||
<div className="signin-col">
|
||||
<div className="signin-brand">
|
||||
<Logo size={30} />
|
||||
<span className="type-wordmark">MINNECT</span>
|
||||
</div>
|
||||
<div className="signin-head">
|
||||
<span className="type-eyebrow">Members</span>
|
||||
<h1 className="signin-title">
|
||||
Human answers for <em>human decisions</em>
|
||||
</h1>
|
||||
<div className="signin-rule" aria-hidden="true" />
|
||||
</div>
|
||||
<form className="signin-form" onSubmit={submit} noValidate>
|
||||
{error && (
|
||||
<p role="alert" className="error">
|
||||
<p role="alert" className="error signin-error">
|
||||
{error}
|
||||
</p>
|
||||
)}
|
||||
<label htmlFor="email">Email</label>
|
||||
<label className="signin-label" htmlFor="email">
|
||||
Email
|
||||
</label>
|
||||
<div className="signin-field">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
|
||||
<rect x="3" y="5" width="18" height="14" rx="3" />
|
||||
<path d="m4 7 8 6 8-6" />
|
||||
</svg>
|
||||
<input
|
||||
id="email"
|
||||
name="email"
|
||||
type="email"
|
||||
autoComplete="username"
|
||||
placeholder="you@company.com"
|
||||
required
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
/>
|
||||
<label htmlFor="password">Password</label>
|
||||
</div>
|
||||
<label className="signin-label signin-label-next" htmlFor="password">
|
||||
Password
|
||||
</label>
|
||||
<div className="signin-field">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
|
||||
<rect x="4.5" y="10.5" width="15" height="10" rx="2.5" />
|
||||
<path d="M8 10.5V8a4 4 0 0 1 8 0v2.5" />
|
||||
</svg>
|
||||
<input
|
||||
id="password"
|
||||
name="password"
|
||||
type="password"
|
||||
autoComplete="current-password"
|
||||
placeholder="Your password"
|
||||
required
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
/>
|
||||
<button type="submit" disabled={busy || !email || !password}>
|
||||
{busy ? "Signing in..." : "Sign in"}
|
||||
</button>
|
||||
</div>
|
||||
<SparkleButton
|
||||
type="submit"
|
||||
className="signin-submit"
|
||||
label={busy ? "Signing in..." : "Sign in"}
|
||||
disabled={busy || !email || !password}
|
||||
/>
|
||||
</form>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
here; the file goes when it is empty. Do not add new rules here.
|
||||
Literal white and black are only text on crimson and video letterboxing. */
|
||||
.center { min-height: 100vh; display: grid; place-items: center; padding: 16px; }
|
||||
.card { width: 100%; max-width: 400px; background: var(--tile); border: 1px solid var(--line); border-radius: 8px; padding: 32px 24px; display: flex; flex-direction: column; gap: 8px; }
|
||||
.card h1 { font-size: 22px; margin: 12px 0 8px; }
|
||||
label { font-size: 14px; font-weight: 500; margin-top: 8px; }
|
||||
input { font: inherit; padding: 12px; border: 1px solid var(--line-2); border-radius: 8px; background: var(--tile-2); color: var(--ink); }
|
||||
input:focus-visible, button:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
/* Sign-in page (spec "Sign in", ADR 0001). Outside .app: one centered column, no breakpoints.
|
||||
Tokens only, so it follows the active theme (dark by default). */
|
||||
.signin {
|
||||
position: relative;
|
||||
min-height: 100vh;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 28px 24px;
|
||||
background: var(--bg);
|
||||
color: var(--ink);
|
||||
}
|
||||
.signin-glow {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: -220px;
|
||||
width: 560px;
|
||||
height: 420px;
|
||||
transform: translateX(-50%);
|
||||
border-radius: 50%;
|
||||
background: radial-gradient(ellipse, color-mix(in srgb, var(--accent), transparent 84%), transparent 65%);
|
||||
pointer-events: none;
|
||||
}
|
||||
.signin-col {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
max-width: 342px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.signin-brand {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
padding-top: 40px;
|
||||
font-size: 15px;
|
||||
}
|
||||
.signin-head {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 14px;
|
||||
text-align: center;
|
||||
margin: 72px 0 40px;
|
||||
}
|
||||
.signin-title {
|
||||
margin: 0;
|
||||
font-family: var(--font-serif), Georgia, serif;
|
||||
font-size: 40px;
|
||||
font-weight: 600;
|
||||
line-height: 1.05;
|
||||
color: var(--ink);
|
||||
}
|
||||
.signin-title em { font-style: italic; font-weight: 500; }
|
||||
.signin-rule {
|
||||
width: 48px;
|
||||
height: 1px;
|
||||
background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--ink), transparent 40%), transparent);
|
||||
}
|
||||
.signin-form { display: flex; flex-direction: column; gap: 12px; }
|
||||
.signin-label {
|
||||
margin: 0;
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.16em;
|
||||
color: var(--ink-3);
|
||||
}
|
||||
.signin-label-next { margin-top: 6px; }
|
||||
.signin-field {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
height: 52px;
|
||||
padding: 0 16px;
|
||||
border-radius: var(--r-ctl);
|
||||
background: var(--tile-2);
|
||||
color: var(--ink-3);
|
||||
box-shadow: inset 0 0 0 1px var(--line-2);
|
||||
transition: box-shadow .25s;
|
||||
}
|
||||
.signin-field:focus-within {
|
||||
box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ink), transparent 45%), 0 0 0 4px color-mix(in srgb, var(--ink), transparent 94%);
|
||||
}
|
||||
.signin-field svg { width: 18px; height: 18px; flex: none; }
|
||||
.signin-field input {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
outline: 0;
|
||||
background: transparent;
|
||||
font: inherit;
|
||||
font-size: 15px;
|
||||
color: var(--ink);
|
||||
}
|
||||
.signin-field input::placeholder { color: var(--ink-3); }
|
||||
.signin-form .signin-submit { margin-top: 18px; width: 100%; height: 54px; }
|
||||
.signin-form .signin-submit:disabled { opacity: .5; cursor: not-allowed; }
|
||||
.signin-error { margin: 0; }
|
||||
Reference in New Issue
Block a user