All Taste components
Mobile screens
Sign in with OTP
Enter the six-digit code sent to a phone number, with a resend timer and a number pad.
6 code boxes · filled / focused / empty · resend countdown · disabled verify · number pad
// Mobile-first page; the same markup maps to React Native via NativeWind (View/TextInput/Pressable).
"use client";
import { useRef, useState } from "react";
import { ChevronLeft } from "lucide-react";
import { cn } from "@/lib/utils";
const LENGTH = 6;
const phone = "+91 98450 12321";
export default function VerifyCodeScreen() {
const [code, setCode] = useState<string[]>(Array(LENGTH).fill(""));
const [seconds] = useState(24);
const inputs = useRef<(HTMLInputElement | null)[]>([]);
const complete = code.every(Boolean);
const setDigit = (i: number, value: string) => {
const digit = value.replace(/[^0-9]/g, "").slice(-1);
setCode((c) => c.map((d, j) => (j === i ? digit : d)));
if (digit && i < LENGTH - 1) inputs.current[i + 1]?.focus();
};
return (
<main className="mx-auto flex min-h-dvh max-w-md flex-col bg-bg font-sans text-fg">
<header className="flex h-12 items-center px-2">
<button type="button" aria-label="Back" className="grid size-11 place-items-center rounded-full hover:bg-surface-2">
<ChevronLeft className="size-[22px]" />
</button>
</header>
<form className="px-4 pt-1" onSubmit={(e) => e.preventDefault()}>
<h1 className="text-2xl font-semibold tracking-tight">Enter the code</h1>
<p className="mt-2 text-sm text-fg-muted">
We sent a 6-digit code to <b className="font-medium tabular-nums text-fg">{phone}</b>.{" "}
<a href="/sign-in" className="font-medium text-primary">Change</a>
</p>
<div role="group" aria-label="One-time code" className="mt-6 grid grid-cols-6 gap-[7px]">
{code.map((d, i) => (
<input
key={i}
ref={(el) => { inputs.current[i] = el; }}
value={d}
onChange={(e) => setDigit(i, e.target.value)}
onKeyDown={(e) => { if (e.key === "Backspace" && !d && i > 0) inputs.current[i - 1]?.focus(); }}
inputMode="numeric"
autoComplete={i === 0 ? "one-time-code" : "off"}
maxLength={1}
aria-label={"Digit " + (i + 1)}
className="h-[52px] w-full rounded border border-border-strong bg-bg text-center text-[22px] font-semibold tabular-nums outline-none focus:border-primary focus:ring-[3px] focus:ring-ring"
/>
))}
</div>
<p className="mt-3 text-xs text-fg-muted">
Didn’t get it?{" "}
{seconds > 0
? <>Resend in <span className="font-medium tabular-nums text-fg">0:{String(seconds).padStart(2, "0")}</span></>
: <button type="button" className="font-medium text-primary">Resend code</button>}
</p>
<button
type="submit"
disabled={!complete}
className={cn("mt-5 h-12 w-full rounded bg-primary text-[15px] font-semibold text-primary-fg hover:bg-primary-hover", "disabled:pointer-events-none disabled:opacity-50")}
>
Verify
</button>
</form>
</main>
);
}
The code uses the Taste Tailwind preset. Make yours on the Taste page with Export my system.