# OTP verification

> A six-digit one-time-passcode entry card for verifying an email, with expiry messaging and a resend action.

A shadcn/ui block from the [@quill](https://www.quilldesignsystem.com) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/quill/otp-verification).

- Page, with a live preview: https://shadcn.exchange/r/quill/otp-verification
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/quill/otp-verification-light-e5852cfa093d6c47.png
- Registry item: https://www.quilldesignsystem.com/r/otp-verification.json
- Categories: auth
- Listed: 2026-10-13, source last changed 2026-10-13

## Install

```bash
npx shadcn@latest add https://www.quilldesignsystem.com/r/otp-verification.json
```

Run it in a project that has shadcn/ui set up. It adds the files below and installs what they depend on.

## Dependencies

- Registry items: `card`, `input-otp`, `label`, `button`

## Notes from the registry

A six-digit one-time-passcode entry card for verifying an email, with expiry messaging and a resend action. Do: State the code's expiry window in the card body ("expires in 10 minutes"), not just in the email. Don't: Leave users guessing why a code that worked a moment ago now fails. Use login-minimal when you're sending the initial one-time code, not verifying a code the user already received — that's a separate step upstream of this card. Use forgot-password when recovery works by emailed link, not a typed code.

## Files

### `registry/blocks/otp-verification.tsx`

```tsx
import {
  Card,
  CardHeader,
  CardTitle,
  CardDescription,
  CardContent,
  CardFooter,
} from '@/components/ui/card'
import {
  InputOTP,
  InputOTPGroup,
  InputOTPSeparator,
  InputOTPSlot,
} from '@/components/ui/input-otp'
import { Label } from '@/components/ui/label'
import { Button } from '@/components/ui/button'

/** A six-digit one-time-passcode entry card for verifying an email, with expiry messaging and a resend action. */
export function OtpVerification() {
  return (
    <Card className="w-[380px]">
      <CardHeader className="text-center">
        <CardTitle>Check your email</CardTitle>
        <CardDescription>
          We sent a six-digit code to <span className="text-foreground">ada@example.com</span>.
        </CardDescription>
      </CardHeader>
      <CardContent className="flex flex-col items-center gap-3">
        <Label htmlFor="otp-code" className="sr-only">
          Verification code
        </Label>
        <InputOTP id="otp-code" maxLength={6}>
          <InputOTPGroup>
            <InputOTPSlot index={0} />
            <InputOTPSlot index={1} />
            <InputOTPSlot index={2} />
          </InputOTPGroup>
          <InputOTPSeparator />
          <InputOTPGroup>
            <InputOTPSlot index={3} />
            <InputOTPSlot index={4} />
            <InputOTPSlot index={5} />
          </InputOTPGroup>
        </InputOTP>
        <p className="text-xs text-muted-foreground">The code expires in 10 minutes.</p>
      </CardContent>
      <CardFooter className="flex-col gap-2">
        <Button className="w-full">Verify</Button>
        <Button variant="link" className="w-full">
          Didn&rsquo;t get it? Resend code
        </Button>
      </CardFooter>
    </Card>
  )
}
```
