Auth
Forgot password
The password-reset request step: an icon badge, one email field, and a clear primary action on a light panel, next to a dark canvas carrying a customer testimonial. Kept deliberately minimal on the form side so it reads as a focused, low-friction step.
How it's built
One field, one action — resist adding anything that competes with the primary task.
The testimonial panel is original, hand-written copy and an initials avatar, not a photo of a real person or a real customer quote — safe placeholder content for a pattern meant to be copy-pasted and re-branded.
Same split rule as the other Auth patterns: real oks-ui components (the form) live on a plain light panel; the dark canvas carries only text we colour ourselves, since oks-ui's dark theme needs `data-theme="dark"` on the document root to activate, not just a dark backdrop.
"Back to log in" is a real `Button variant="link"` with `startContent` for the arrow icon — not a raw anchor. Passing `href` (with no `type`) makes `Button` render as an `<a>` automatically.
"Forgot password?" is a real `PageTitle` (safe to use its default styling here, since this panel is genuinely light and theme-driven); the shield icon badge above it and the "MK" initials avatar on the dark testimonial canvas are both real `Avatar` components too — the badge is `isBordered`-free, using a plain `classNames={{ base: "border border-line bg-transparent" }}` override for a simple outlined square instead of oks-ui's own multi-ring bordered style.
Source
One file · copy & pasteimport { Avatar } from "oks-ui/avatar";
import { Button } from "oks-ui/button";
import { Form, FormFieldSet } from "oks-ui/form-field-set";
import { PageTitle } from "oks-ui/page-title";
import { ShieldIcon } from "../../showcase/icons";
function ArrowLeftIcon({ size = 16 }: { size?: number }) {
return (
<svg width={size} height={size} viewBox="0 0 16 16" fill="none" aria-hidden="true">
<path
d="M13 8H3M3 8l4-4M3 8l4 4"
stroke="currentColor"
strokeWidth="1.6"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
);
}
export function ForgotPassword() {
return (
<div className="@container w-full bg-paper-raised">
<div className="grid @2xl:min-h-[560px] @2xl:grid-cols-2">
{/* form panel */}
<div className="flex flex-col justify-center p-8 @2xl:p-14">
<div className="mx-auto flex w-full max-w-sm flex-col gap-6">
<span className="text-sm font-bold uppercase tracking-[0.2em] text-ink-faint">
Brand
</span>
<div className="flex flex-col gap-5">
<Avatar
icon={<ShieldIcon size={20} />}
radius="md"
size="lg"
classNames={{ base: "border border-line bg-transparent", icon: "text-accent" }}
/>
<PageTitle
as="h1"
title="Forgot password?"
subtitle="No worries, we'll send you reset instructions."
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",
}}
/>
</div>
<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 } }}
/>
<Button type="submit" color="primary" fullWidth>
Reset password
</Button>
</Form>
<Button
href="/sign-in"
variant="link"
size="sm"
startContent={<ArrowLeftIcon />}
className="h-auto justify-center p-0 text-[0.85rem] font-medium text-ink-muted no-underline"
>
Back to log in
</Button>
</div>
</div>
{/* testimonial panel — original copy, no photo of a real person */}
<div className="relative hidden flex-col overflow-hidden bg-[#04151a] p-12 @2xl:flex">
<div
aria-hidden="true"
className="absolute inset-0"
style={{
background:
"radial-gradient(120% 90% at 85% 15%, color-mix(in oklab, #0891b2 45%, transparent) 0%, transparent 55%), " +
"radial-gradient(90% 70% at 10% 90%, color-mix(in oklab, #0f766e 45%, transparent) 0%, transparent 60%), " +
"linear-gradient(160deg, #04151a 0%, #04262b 55%, #062f2c 100%)",
}}
/>
<div
aria-hidden="true"
className="absolute -right-20 top-1/4 h-72 w-72 rounded-full opacity-30 blur-3xl"
style={{ background: "#22d3ee" }}
/>
<div className="relative z-10 flex h-full flex-col justify-center gap-6">
<span className="text-[3rem] font-serif leading-none text-white/25" aria-hidden="true">
“
</span>
<p className="max-w-md text-[1.5rem] font-medium leading-snug tracking-tight text-white">
We cut our onboarding time in half within the first month —
support tickets dropped right along with it.
</p>
<div className="mt-2 flex items-center gap-3">
<Avatar
name="Maya Kessler"
radius="full"
classNames={{ base: "bg-white/10", name: "text-white" }}
/>
<div>
<p className="text-sm font-semibold text-white">Maya Kessler</p>
<p className="text-[0.8rem] text-white/60">
Head of Ops, Northwind Labs
</p>
</div>
</div>
</div>
</div>
</div>
</div>
);
}