Skip to content

Code input

Enter a one-time code by typing, pasting or, where the browser supports it, autofill from a message, and let the app know when the code is complete.

Check your phone

A code went to +1 •••• 0100

Enter a 6-character code.

246810 is the right one here.

No code yet?
<script setup lang="ts">import { ref } from 'vue'import { UiCard, UiField, UiCodeInput, UiButton } from 'grani' // The app checks the code; a wrong one is cleared, so the same code can be typed again.const otp = ref('') const error = ref('') const verified = ref(false) function check(value: string) {  if (value === '246810') {    verified.value = true    error.value = ''  } else {    error.value = 'That code is not right. Try again.'    otp.value = ''  }} // A new code is on its way: the field and its error start over.function resend() {  otp.value = ''  error.value = ''  verified.value = false}</script> <template>  <UiCard    title="Check your phone"    description="A code went to +1 •••• 0100"    class="w-full max-w-sm"  >    <UiField      label="Code"      :description="verified ? 'Checked: the code is right.' : '246810 is the right one here.'"      :error="error || undefined"      required    >      <UiCodeInput v-model="otp" @complete="check" @update:model-value="verified = false" />    </UiField>    <template #footer>      <span class="me-auto text-xs text-fg-muted">No code yet?</span>      <UiButton variant="ghost" size="xs" @click="resend">Send it again</UiButton>    </template>  </UiCard></template>

Also called otp input, one-time code input, pin input, verification code.

Usage

<UiCodeInput v-model="value" />

With GraniResolver in the Vite config, a template needs no import: set it up once.

API

Name · typeDefaultDescription
Value
modelValue*stringThe entered code (v-model); empty is ''.
Behavior
lengthnumber= 66Number of characters in the code, a whole number from 1 to 100; anything else is held to that and warned about in development.
inputModenumeric | text= "numeric""numeric"Keyboard shown on a phone. numeric for SMS, PIN, and authenticator codes. text for codes with letters.
patternstring | RegExpAllowed characters, tested one character at a time (not the whole code). A RegExp or its source. When omitted, numeric allows digits and text allows letters and digits.
separatorboolean= falsefalseShows a short rule between the code groups.
Look
sizexs | sm | md= "md""md"Step of the control ladder for the cells.
Form and access
disabledboolean= falsefalsePrevents entering and editing the code.
invalidboolean= falsefalseMarks the control as invalid. Inside UiField, the error state sets this automatically.
requiredbooleanStandalone only: a value is needed, said to a reader and to a form (native required). Inside UiField the field's required says so.
namestringNative name for forms.
idstringOwn id when standalone. Inside UiField, the field's id takes precedence.
ariaLabelstringAccessible name when there is no visible label.

Attributes: class and style stay on the outer element; the rest (native attributes, aria-*, data-testid) reach the control inside it.

When to use another component

When you needTake
A passwordInput type="password"
A number or a text of any lengthInput
A code shown to copy and never typedCopy button