Xzero UI
Pro library

Two-factor setupPro

A two-factor setup card where you scan a real, working authenticator QR code, type the 6-digit code into slots that move to the next box on their own, and save your backup codes before it turns on. Every step shares one fixed-size card, so it moves between steps with a short slide and never changes size.

$ pnpm dlx shadcn@4.23.0 add @xzero-ui-pro/two-factor-setup
Live · keyboard ready

Use this as the authenticator app step in account or workspace security settings. Pass secret and backupCodes from your server, along with issuer and account. Wire verifyCode(code, signal) to your TOTP check: return true to continue or false to show the mismatch error. Turn two-factor on in onEnable(signal); if it rejects, an inline error shows. Use onDone to go back to settings, onCancel to show a Cancel button, and onStepChange for analytics. Once you pass verifyCode, the simulated authenticator row and the local check go away.

When to use

When not to use

Installation

Register both Xzero UI namespaces in your project's components.json:

{
  "registries": {
    "@xzero-ui": "https://mcp.xzero.co.uk/r/{name}.json",
    "@xzero-ui-pro": "https://mcp.xzero.co.uk/r/pro/{name}.json"
  }
}
npx shadcn@4.23.0 add @xzero-ui-pro/two-factor-setup

Install xzero-foundation once, and import @/components/xzero/foundation.css in your app root. No Xzero token is used by this snapshot. For sample portraits, photos, fonts, or logos, download https://mcp.xzero.co.uk/install-assets.mjs and run node xzero-install-assets.mjs <receiving-project>.

Usage

import { TwoFactorSetup } from "@/components/xzero/blocks/two-factor-setup/two-factor-setup";

export function SecurityTwoFactor({ setup }: { setup: { secret: string; codes: string[] } }) {
  return (
    <TwoFactorSetup
      issuer="Acme"
      account="dana@acme.com"
      secret={setup.secret}
      backupCodes={setup.codes}
      verifyCode={async (code, signal) => {
        const res = await fetch("/api/2fa/verify", { method: "POST", body: JSON.stringify({ code }), signal });
        return res.ok;
      }}
      onEnable={signal => fetch("/api/2fa/enable", { method: "POST", signal }).then(() => undefined)}
      onDone={() => router.push("/settings/security")}
    />
  );
}

API reference

TwoFactorSetup

A three step authenticator app setup card: scan a real TOTP QR code (or copy the setup key), confirm a six digit code, save backup codes, then a final enabled state. With no props it is a working demo that checks real codes for its sample secret.

PropTypeDefaultDescription
issuerstring"Northwind"Product name written into the otpauth URI and shown in the authenticator entry.
accountstring"maya@northwind.io"Account label written into the otpauth URI, usually the email.
secretstring"QK7MR2XD5LVNA3WE"Base32 TOTP secret from your server. The QR code and grouped setup key are built from it.
backupCodesstring[]8 sample codesOne-time recovery codes from your server, shown in a grid and used for Download and Copy.
verifyCode(code: string, signal: AbortSignal) => Promise<boolean>–Checks the six digit code on your server. Resolve true to continue, false to show the mismatch error, reject to show a retry error. Without it the card verifies real TOTP codes for secret locally and shows a simulated authenticator entry you can click to fill the code.
onEnable(signal: AbortSignal) => Promise<void> | void–Called from Turn on after the person confirms they saved the codes. Persist two-factor here; reject to show an inline error.
onCancel() => void–Shows a Cancel button on the first step.
onDone() => void–Called from Done on the enabled state. Without it, Done restarts the demo.
onStepChange(step: "scan" | "verify" | "backup" | "enabled") => void–Fires whenever the step changes, for analytics or routing.
addedLabelstring"Added Oct 27, 2026"Date label for the authenticator row on the enabled state.
classNamestring–Class for the card root.

Keyboard interactions

KeysAction
0-9Types a digit and moves to the next slot. The sixth digit submits.
BackspaceClears the slot, or the previous slot when this one is empty, and moves back.
Left / Right, Home / EndMoves between code slots.
Cmd/Ctrl + VPastes a full code into all six slots from any slot and submits.
EnterSubmits a complete code.
TabMoves through the setup key copy button, slots, checkbox, Download, Copy, Back and the primary action.

Accessibility

Motion

Responsive behavior

Performance

Notes for AI

Guidance for AI tools

Blocks are complete, self-contained screens with sample data. Replace the sample data and connect the callbacks described above. Follow the declared prop types and do not invent props. Keep keyboard access, reduced motion support, and both light and dark themes intact when adapting it.

Full library index: https://ui.xzero.co.uk/llms.txt

Browse all components