Verify Code
Web/MobileA one-time code field with digit boxes, optional groups, resend timer, description, and error. Values always display as Persian digits.
زمان باقیمانده تا دریافت کد مجدد
۰۱:۰۰Installation
pnpm dlx cubix-ui@latest add verify-code --base radixUsage
import {
VerifyCode,
VerifyCodeControl,
VerifyCodeLabel,
VerifyCodeResend,
} from "@/components/cubix/verify-code"
<VerifyCode className="w-full max-w-sm">
<VerifyCodeLabel>کد تایید</VerifyCodeLabel>
<VerifyCodeControl />
<VerifyCodeResend />
</VerifyCode>
Composition
Compose label, control, resend, help text, and error under VerifyCode. VerifyCodeControl renders digit boxes from length and optional groups. Digits always display in Persian. Filling a box moves focus forward; Backspace on an empty box moves back. Paste a full code to fill every box.
VerifyCode
├── VerifyCodeLabel
├── VerifyCodeControl
│ ├── VerifyCodeDigit
│ └── VerifyCodeSeparator
├── VerifyCodeResend
├── VerifyCodeDescription
└── VerifyCodeErrorAccessibility
Each digit box is named by position. Auto-advance and Backspace keep keyboard entry on one path. VerifyCodeResend exposes a clear countdown and becomes a button when ready. VerifyCodeDescription and VerifyCodeError are announced through aria-describedby. Set name on the root to submit a single hidden value for the full code.
Examples
Length
Change how many digit boxes render with the length prop.
زمان باقیمانده تا دریافت کد مجدد
۰۱:۰۰زمان باقیمانده تا دریافت کد مجدد
۰۱:۰۰Groups
Pass groups to insert separators between digit runs (for example 3-3).
زمان باقیمانده تا دریافت کد مجدد
۰۱:۰۰زمان باقیمانده تا دریافت کد مجدد
۰۱:۰۰Resend
Use VerifyCodeResend with duration for a countdown before the user can request a new code.
زمان باقیمانده تا دریافت کد مجدد
۰۲:۰۰Filled
Pass defaultValue on the root to show a complete code.
زمان باقیمانده تا دریافت کد مجدد
۰۱:۰۰Invalid
Set invalid on the root to apply destructive styles and show VerifyCodeError.
زمان باقیمانده تا دریافت کد مجدد
۰۱:۰۰Disabled
Disable the field to block every digit and the resend control. Label and description stay readable.
زمان باقیمانده تا دریافت کد مجدد
۰۱:۰۰Sizes
Two heights ship by default: default (40px) and lg (48px). Use className for any other size.
زمان باقیمانده تا دریافت کد مجدد
۰۱:۰۰زمان باقیمانده تا دریافت کد مجدد
۰۱:۰۰In a form
Set name on the root so the combined code is submitted with the form, and pair the field with Cubix Button.
Custom styling
Every part accepts a className merged with the shipped cn helper.
زمان باقیمانده تا دریافت کد مجدد
۰۱:۰۰API Reference
Note: Parts render data-slot attributes (verify-code, verify-code-label, verify-code-control, verify-code-digit, verify-code-separator, verify-code-resend, verify-code-description, verify-code-error) for targeting in tests and parent selectors. Use the same props on Base UI, React Aria, and Radix.
VerifyCode
| Prop | Type | Default | Description |
|---|---|---|---|
| length | number | 6 | Number of digit boxes to render (clamped between 4 and 8). Inherited by VerifyCodeControl when it auto-renders digits. |
| groups | number[] | - | Optional digit grouping. Sum must equal length. Inserts a - between groups when VerifyCodeControl auto-renders - for example [3, 3] or [2, 2, 2]. Ignored when invalid or when you pass custom digit children. |
| size | "default" | "lg" | "default" | Height for the digit boxes: default 40px, lg 48px. Inherited by VerifyCodeControl unless overridden. |
| disabled | boolean | false | Disables the field and prevents interaction. Forwarded to every digit on every base. |
| invalid | boolean | false | Marks the field as invalid and applies a destructive border on the digit boxes. |
| defaultValue | string | - | Initial code as a digit string (Persian or Latin). Split across the boxes up to length. |
| value | string | - | Controlled code string. Pair with onValueChange when the parent owns the value. |
| onValueChange | (value: string) => void | - | Called with the combined Persian-digit string whenever a digit changes. |
| name | string | - | Writes a hidden input with the combined code (Persian digits, no separators) for form submit. |
| className | string | - | Additional Tailwind classes merged with the root styles (last one wins). |
VerifyCodeControl
| Prop | Type | Default | Description |
|---|---|---|---|
| size | "default" | "lg" | - | Overrides the size from VerifyCode. Height matches the default and lg sizes. |
| digitClassName | string | - | Classes merged onto each auto-rendered VerifyCodeDigit. Ignored when you pass custom digit children. |
| children | React.ReactNode | - | Optional. When omitted, VerifyCodeControl renders length digit boxes and inserts VerifyCodeSeparator between groups when groups is set on the root. Pass VerifyCodeDigit and VerifyCodeSeparator nodes to customize composition. |
| className | string | - | Additional Tailwind classes merged with the control styles (last one wins). |
VerifyCodeDigit
| Prop | Type | Default | Description |
|---|---|---|---|
| index | number | - | Zero-based position of the digit box. Required when composing VerifyCodeDigit manually. |
| placeholder | string | "" | Hint text shown when the digit box is empty. Empty by default. |
| inputMode | "numeric" | "numeric" | Locked to numeric so mobile keyboards show a number pad. |
| className | string | - | Additional Tailwind classes merged with the digit styles (last one wins). |
| ...props | Omit<React.ComponentProps<'input'>, 'type' | 'inputMode' | 'spellCheck' | 'maxLength' | 'value' | 'defaultValue'> | - | Native input attributes are forwarded. type, inputMode, spellCheck, maxLength, value, and defaultValue stay locked. Use parseVerifyCodeValue / formatVerifyCodeValue for the combined string. |
VerifyCodeSeparator
| Prop | Type | Default | Description |
|---|---|---|---|
| children | React.ReactNode | "-" | Separator content between digit groups. Defaults to a hyphen. |
| className | string | - | Additional Tailwind classes merged with the separator styles (last one wins). |
VerifyCodeResend
| Prop | Type | Default | Description |
|---|---|---|---|
| duration | number | 60 | Countdown length in seconds before resend is available. Default is 1 minute (60). Pass 120 for two minutes. |
| waitingLabel | React.ReactNode | "زمان باقیمانده تا دریافت کد مجدد" | Helper text shown beside the muted timer badge while counting down. |
| expiredLabel | React.ReactNode | "دریافت مجدد کد تایید" | Helper text shown beside the badge after the countdown reaches zero. |
| resendLabel | React.ReactNode | "دریافت مجدد" | Label inside the muted badge after the countdown ends. Clicking the badge restarts the timer. |
| onResend | () => void | - | Called when the user clicks the badge to resend. The countdown restarts automatically after the click. |
| className | string | - | Additional Tailwind classes merged with the resend row styles (last one wins). |
VerifyCodeLabel / Description / Error
| Prop | Type | Default | Description |
|---|---|---|---|
| children | React.ReactNode | - | Label text, helper description, or error message content. |
| className | string | - | Additional Tailwind classes merged with the part styles (last one wins). |
| ...props | HTML attributes | - | Native attributes for the rendered element are forwarded. |