Auth
Sign-in screen
A premium two-column auth screen: an editorial brand panel with a feature highlight card on one side, a complete email/password form with Google SSO, remember-me, and forgot-password on the other. FormFieldSet handles the field types and validation; Form collects the values on submit — no form library.
How it's built
The layout uses a container query (`@container` on the outer wrapper, `@2xl:grid-cols-2`) so it stays a genuine split-screen even scaled down inside a card, and gracefully collapses to a single column below that width — the brand panel hides entirely on narrow screens, leaving just the form.
The outer wrapper carries no border, radius, or shadow of its own — when this pattern is shown inside a mock-browser frame (like this preview), that frame IS the container; a second rounded card floating inside it would just be a frame-in-a-frame. Drop the wrapper's own chrome when embedding this in a real page too, unless you want a literal floating card.
`@2xl:min-h-[640px]` gives the split real presence instead of a short strip — applied only at the breakpoint where the two columns actually appear, so the mobile single-column view isn't forced to an arbitrary height it doesn't need.
`whitespace-nowrap` on "Forgot password" stops it wrapping to two lines next to the checkbox at in-between widths — small fixed-width text sitting beside a flexible one is exactly where accidental wraps happen.
`validation={{ rules: { required: true, email: true } }}` wires up inline errors and `aria-invalid` — nothing else to do. `type="password"` gets a reveal toggle for free.
Standalone `Checkbox` (imported from `oks-ui/form-field-set`, not part of a `FormFieldSet` group) takes a `label` prop — passing children instead spreads them onto the underlying `<input>` and breaks it.
The brand panel's feature card fills what would otherwise be dead vertical space between the logo and the headline — an empty gradient reads as unfinished, not premium.
Each feature-list icon is a real `Avatar`, and "Welcome back" is a real `PageTitle` — not raw spans/headings. The feature icons sit on the dark brand panel, so they're tinted through the `classNames` slot instead of `color`, since that panel is outside oks-ui's `data-theme`-scoped theme system; "Welcome back" sits on the genuinely light form panel, so `PageTitle` needs no such workaround.
`PageTitle`'s own `.oksPageTitle` wrapper is `display: inline-flex` with no set direction — built for a compact icon+title(+short subtitle) sitting in one row, not the classic stacked "big heading, paragraph below" layout this pattern (and most page headers) actually want. Pass `classNames={{ base: "flex-col items-start" }}` to stack the title above the subtitle instead of beside it.
The "Sign in with Google" button is a real oks-ui `Button` with `startContent` — the multi-colour G mark is just an inline SVG, the same as any other icon slot.
"Forgot password", "Sign up", and the dark panel's headline are real oks-ui components too — not raw `<a>`/`<h1>` tags. `Button` is polymorphic: pass `href` (with no `type`) and it renders as an `<a>` automatically, so `variant="link"` plus a `no-underline` override gives a proper accessible, keyboard-focusable text link instead of hand-rolled anchor styling.
Source
One file · copy & pasteimport { Avatar } from "oks-ui/avatar";
import { Button } from "oks-ui/button";
import { Checkbox, Form, FormFieldSet } from "oks-ui/form-field-set";
import { PageTitle } from "oks-ui/page-title";
import { CheckIcon, ShieldIcon, ZapIcon } from "../../showcase/icons";
// A small, standard multi-colour "G" mark for the SSO button — not
// reproducing any photo or illustration, just the ubiquitous service icon
// every "Sign in with Google" button uses.
function GoogleIcon() {
return (
<svg width="18" height="18" viewBox="0 0 18 18" aria-hidden="true">
<path
fill="#4285F4"
d="M17.64 9.2c0-.64-.06-1.25-.16-1.84H9v3.48h4.84c-.21 1.13-.85 2.09-1.81 2.73v2.26h2.92c1.71-1.57 2.69-3.88 2.69-6.63z"
/>
<path
fill="#34A853"
d="M9 18c2.43 0 4.47-.8 5.96-2.18l-2.92-2.26c-.81.54-1.84.87-3.04.87-2.34 0-4.32-1.58-5.03-3.71H.96v2.33C2.44 15.98 5.48 18 9 18z"
/>
<path
fill="#FBBC05"
d="M3.97 10.72c-.18-.54-.28-1.12-.28-1.72s.1-1.18.28-1.72V4.95H.96A8.99 8.99 0 0 0 0 9c0 1.45.35 2.83.96 4.05l3.01-2.33z"
/>
<path
fill="#EA4335"
d="M9 3.58c1.32 0 2.51.45 3.44 1.35l2.59-2.59C13.46.89 11.43 0 9 0 5.48 0 2.44 2.02.96 4.95l3.01 2.33C4.68 5.16 6.66 3.58 9 3.58z"
/>
</svg>
);
}
const features = [
{ icon: <ZapIcon size={16} />, text: "Real-time sync across every device" },
{ icon: <ShieldIcon size={16} />, text: "Enterprise-grade encryption by default" },
{ icon: <CheckIcon size={16} />, text: "Pick up your last session instantly" },
];
export function SignIn() {
return (
<div className="@container w-full bg-paper-raised">
<div className="grid @2xl:min-h-[640px] @2xl:grid-cols-2">
{/* visual panel — original abstract art, not a stock photo */}
<div className="relative hidden flex-col overflow-hidden bg-[#04151a] p-9 @2xl:flex">
<div
aria-hidden="true"
className="absolute inset-0"
style={{
background:
"radial-gradient(120% 90% at 15% 10%, color-mix(in oklab, #0f766e 55%, transparent) 0%, transparent 55%), " +
"radial-gradient(90% 70% at 90% 85%, color-mix(in oklab, #0891b2 45%, transparent) 0%, transparent 60%), " +
"linear-gradient(160deg, #04151a 0%, #04262b 55%, #062f2c 100%)",
}}
/>
<div
aria-hidden="true"
className="absolute -left-24 top-1/3 h-72 w-72 rounded-full opacity-40 blur-3xl"
style={{ background: "#14b8a6" }}
/>
<div
aria-hidden="true"
className="absolute -right-16 bottom-0 h-64 w-64 rounded-full opacity-30 blur-3xl"
style={{ background: "#22d3ee" }}
/>
<div className="relative z-10 flex h-full flex-col justify-between gap-10">
<span className="text-sm font-bold uppercase tracking-[0.2em] text-white">
Brand
</span>
{/* glass card filling the middle of the panel */}
<div className="rounded-[var(--r-lg)] border border-white/15 bg-white/[0.06] p-5 backdrop-blur-sm">
<p className="text-[0.7rem] font-semibold uppercase tracking-[0.14em] text-white/50">
Why teams switch
</p>
<ul className="mt-4 flex flex-col gap-3.5">
{features.map((f) => (
<li key={f.text} className="flex items-center gap-3 text-white">
<Avatar
icon={f.icon as never}
radius="full"
size="sm"
classNames={{ base: "bg-white/10", icon: "text-[#5eead4]" }}
/>
<span className="text-[0.9rem] leading-snug">{f.text}</span>
</li>
))}
</ul>
</div>
<PageTitle
as="h1"
title="Pick up right where you left off."
subtitle="Sign in to sync your projects, resume your last session, and keep every device in step — everything's exactly where you left it."
classNames={{
base: "flex-col items-start gap-4",
title: "text-[2rem] font-bold leading-[1.1] tracking-tight text-white",
subtitle: "mt-0 max-w-sm text-sm leading-relaxed text-white/70",
}}
/>
</div>
</div>
{/* form panel — fills its half edge to edge; the content inside is
capped to a comfortable reading width and centred, so fields
don't stretch absurdly wide on a large screen. */}
<div className="flex flex-col justify-center p-8 @2xl:p-12">
<div className="mx-auto flex w-full max-w-md flex-col gap-6">
<PageTitle
as="h2"
title="Welcome back"
subtitle="Welcome back! Please enter your details."
classNames={{
base: "flex-col items-start",
title: "text-[1.6rem] font-bold tracking-tight text-ink",
subtitle: "mt-1.5 text-[0.9rem] text-ink-muted",
}}
/>
<Form onSubmit={(data) => console.log(data)} className="flex flex-col gap-4">
<FormFieldSet
type="email"
name="email"
label="Email"
placeholder="Enter your email"
validation={{ rules: { required: true, email: true } }}
/>
<FormFieldSet
type="password"
name="password"
label="Password"
placeholder="Enter your password"
validation={{ rules: { required: true, minLength: 8 } }}
/>
<div className="flex items-center justify-between gap-3">
<Checkbox name="remember" label="Remember me" />
<Button
href="#forgot-password"
onClick={(e) => e.preventDefault()}
variant="link"
size="sm"
className="h-auto shrink-0 whitespace-nowrap p-0 text-[0.85rem] font-medium text-accent no-underline"
>
Forgot password
</Button>
</div>
<Button type="submit" color="primary" fullWidth>
Sign in
</Button>
<Button variant="bordered" fullWidth startContent={<GoogleIcon />}>
Sign in with Google
</Button>
</Form>
<p className="text-center text-[0.85rem] text-ink-muted">
Don’t have an account?{" "}
<Button
href="#sign-up"
onClick={(e) => e.preventDefault()}
variant="link"
size="sm"
className="h-auto p-0 align-baseline text-[0.85rem] font-semibold text-accent no-underline"
>
Sign up
</Button>
</p>
</div>
</div>
</div>
</div>
);
}