Status card plus QR pairing, setup key, and one-time backup codes.
Require a verification code in addition to your password at sign-in.
JBSW Y3DP EHPK 3PXP QK7M 30XAEach code signs you in once if you lose your authenticator.
Install with the CLI, or add the packages and paste the source below.
Add Account security to your app with its source-owned dependencies.
npx cronus-ui add account-security
Install the Cronus UI packages, then paste the block below.
Copy the source for Two-factor setup. Every class is a semantic token, so it re-themes with your app.
import {Badge,Button,Card,CardContent,CardDescription,CardFooter,CardHeader,CardTitle,CopyButton,Separator,Switch,} from "@cronus-ui/ui";import { Download, RefreshCw, ShieldCheck } from "lucide-react";const qrModules = ["#####...#####","#...#.#.#...#","#.#.#..##.#.#","#...#.#.#...#","#####.#.#####","......#......","#.#.#.#.#.#.#","..#..##..#.#.","#####.#.##..#","#...#..##.#..","#.#.#.#..###.","#...##..#..##","#####..#.#.#.",];const qrCells = qrModules.flatMap((row, y) =>row.split("").flatMap((cell, x) => (cell === "#" ? [{ x, y }] : [])),);const setupSteps = [{title: "Install an authenticator app",detail: "1Password, Google Authenticator, and Authy all work.",},{title: "Scan the QR code",detail: "Or enter the setup key below manually.",},{title: "Enter the 6-digit code",detail: "Confirm the first code to finish pairing.",},];const backupCodes = ["QK7M-4H2X","8PWD-J3RT","XN5C-U9LB","M2FA-D6KQ","7VGH-P0SZ","RJ4E-W8YN","B3TU-K5MC","H9QX-A1DF",];export function AccountSecurityTwoFactorBlock() {return (<sectionaria-label="Two-factor authentication settings"className="mx-auto flex w-full max-w-2xl flex-col gap-6"><Card className="shadow-md"><CardContent className="flex flex-wrap items-center gap-4"><span className="inline-flex size-11 shrink-0 items-center justify-center rounded-xl bg-success/10 text-success"><ShieldCheck className="size-5" aria-hidden="true" /></span><div className="flex min-w-0 flex-1 flex-col gap-0.5"><div className="flex flex-wrap items-center gap-2"><span className="font-medium text-fg">Two-factor authentication</span><Badge variant="success">Enabled</Badge></div><p className="text-sm text-fg-secondary">Require a verification code in addition to your password at sign-in.</p></div><Switch defaultChecked aria-label="Toggle two-factor authentication" /></CardContent></Card><Card className="gap-0 pb-0 shadow-md"><CardHeader><CardTitle className="font-display text-lg">Authenticator app</CardTitle><CardDescription>Pair an app that generates rotating 6-digit codes for this account.</CardDescription></CardHeader><CardContent className="flex flex-col gap-6 pt-6 sm:flex-row"><div className="h-fit w-fit shrink-0 rounded-xl border border-border bg-surface-inset p-3"><svgviewBox="0 0 13 13"role="img"aria-label="QR code that pairs this account with an authenticator app"shapeRendering="crispEdges"className="block size-36 text-fg">{qrCells.map((cell) => (<rectkey={`qr-${cell.x}-${cell.y}`}x={cell.x}y={cell.y}width={1}height={1}fill="currentColor"/>))}</svg></div><div className="flex min-w-0 flex-1 flex-col gap-4"><ol className="flex flex-col gap-3">{setupSteps.map((step, index) => (<li key={step.title} className="flex items-start gap-3"><span className="flex size-6 shrink-0 items-center justify-center rounded-full bg-surface-inset text-xs font-medium text-fg-secondary">{index + 1}</span><div className="flex min-w-0 flex-col gap-0.5"><span className="text-sm font-medium text-fg">{step.title}</span><span className="text-xs text-fg-tertiary">{step.detail}</span></div></li>))}</ol><div className="flex items-center gap-1 rounded-lg border border-border bg-surface-inset py-1 pe-1 ps-3"><code className="min-w-0 flex-1 truncate font-mono text-xs text-fg-secondary">JBSW Y3DP EHPK 3PXP QK7M 30XA</code><CopyButtonvalue="JBSWY3DPEHPK3PXPQK7M30XA"size="icon-sm"copyLabel="Copy setup key"className="shrink-0"/></div></div></CardContent><Separator className="my-6" /><CardContent className="flex flex-col gap-4"><div className="flex flex-wrap items-center gap-2"><div className="flex min-w-0 flex-1 flex-col gap-0.5"><span className="font-medium text-fg">Backup codes</span><p className="text-sm text-fg-secondary">Each code signs you in once if you lose your authenticator.</p></div><CopyButtonvalue={backupCodes.join("\n")}variant="outline"size="icon-sm"copyLabel="Copy all backup codes"/><Button variant="outline" size="icon-sm"><Download className="size-3.5" aria-hidden="true" /><span className="sr-only">Download backup codes</span></Button></div><ul className="grid grid-cols-2 gap-2 sm:grid-cols-4">{backupCodes.map((code) => (<likey={code}className="rounded-lg border border-border bg-surface-inset px-2 py-1.5 text-center font-mono text-xs text-fg-secondary">{code}</li>))}</ul></CardContent><Separator className="mt-6" /><CardFooter className="justify-between gap-3 py-5"><span className="text-xs text-fg-tertiary">8 of 8 codes left · Generated Jun 02, 2026</span><Button variant="ghost" size="sm"><RefreshCw className="size-3.5" aria-hidden="true" />Regenerate</Button></CardFooter></Card></section>);}
Require a verification code in addition to your password at sign-in.
JBSW Y3DP EHPK 3PXP QK7M 30XAEach code signs you in once if you lose your authenticator.