Skip to content
Tier

One time code

Pro

A one-time code typed into a row of boxes, one character each: the code an email or authenticator app gives. It is one text field underneath, so a screen reader hears one field, the phone's autofill and a paste fill every box at once, and Backspace works as in any field. Characters the code can't hold are dropped as they're typed or pasted; letters are upper-cased, and digits typed in Arabic-Indic or Persian script are kept as 0 to 9. The boxes run left to right in a right-to-left page too, as the code was written, and the highlighted box follows the caret.

Name it with a <label> around it or Field. After a refused code, set attend with focus moved to it, as for an Input.

Markdown
Version 5.2.0· other versions

This page is for 5.2.0, the current release. An earlier release’s page is the Markdown that release published, so the docs match the version you have installed (candor-lock.json records it).

Not in the docs of 1.3.0, 1.4.0, 1.5.0, 1.5.1, 1.6.0, 1.7.0, 1.8.0, 1.8.1, 1.9.0, 1.9.1, 2.0.0, 2.1.0, 2.2.0, 2.3.0, 2.4.0, 2.5.0, 2.5.1, 2.6.0, 2.6.1 and 2.6.2: the page came later, or had another name then.

Docs pages weren’t kept for 1.0.0, 1.0.1, 1.1.0, 1.1.1, 1.2.0 and 1.2.1: they are kept from 1.3.0 on, and before that only llms.txt was published.

Preview

Loading the preview

Install

With the Candor CLI

First time? Get started sets up the registry and theme. Or with shadcn directly: npx shadcn@latest add @candor/one-time-code

Brings in: motion, tokens, utils

Usage

TSX · The example above
"use client"

import * as React from "react"
import { Field } from "@/components/candor/ui/field"
import { OneTimeCode } from "@/components/candor/ui/one-time-code"

// One field underneath: autofill and paste fill every box. Nothing is sent when the last box fills unless you send it.
export default function Example() {
  const [code, setCode] = React.useState("")
  const [checked, setChecked] = React.useState<string | null>(null)
  return (
    <div className="flex flex-col gap-3">
      <Field label="Code from your authenticator app" hint="Six digits.">
        <OneTimeCode value={code} onValueChange={setCode} onComplete={setChecked} />
      </Field>
      <p className="text-sm text-muted-foreground" aria-live="polite">
        {checked ? `Checking ${checked}…` : ""}
      </p>
    </div>
  )
}

<OneTimeCode>

PropTypeDefaultDescription
lengthnumber | undefined6How many characters the code has. Defaults to 6.
kindOneTimeCodeKind | undefined"numeric"Digits only (the default), or digits and letters.
valuestring | undefined—The code typed so far, when you control it.
defaultValuestring | undefined—The code at first, when you don't control it.
onValueChange((code: string) => void) | undefined—Called with the code as it changes, already cleaned of characters it can't hold.
onComplete((code: string) => void) | undefined—Called once the last box is filled, with the whole code. Submit from here if you like; nothing is sent for you.
attendboolean | undefined—Plays one attention ring on the boxes as it turns true, while the code is `aria-invalid`. Clear it from `onAnimationEnd` or when the person types.

Also takes the props of Omit<React.ComponentProps<"input">, "value" | "defaultValue" | "type" | "maxLength" | "onChange">.

Motion

MomentFamilyWhat it does
invalidattentionOne ring grows and fades around the boxes when `attend` turns on while the code is `aria-invalid`, once. It never plays while the person types; the boxes shake only if the brand draws it as the Pro `jolt` (a locked control's shake is `refuse`). A code that mounts with `attend` set shows nothing until it is set again.

Set with --cd-motion-one-time-code-<moment>-* in your brand file; the families are in the design reference.

Types

OneTimeCodeKind
Which characters a code can hold.
"numeric" | "alphanumeric"