Skip to content
Components

Code entry

The confirmation-code entry: six boxes with one keyboard model — type to advance, backspace to retreat, paste anywhere to fill the lot.

Live

The invalid state: danger border and the one sanctioned nudge — 3px, transform-only.

Code
<GdOtpInput v-model="code" @complete="verify" />

<GdOtpInput v-model="code" invalid />   <!-- that code was wrong -->

API

Props

PropTypeDefault
modelValuestring""

The code so far, as `v-model`. Non-digits are stripped and the string is clamped to `length`.

lengthnumber6

How many boxes. Also the group's accessible name — "6-digit code" — and the point at which `complete` fires.

disabledboolean—

Every box inert, on the disabled surface.

invalidboolean—

Danger border on every box plus the one sanctioned nudge: 3px, transform-only. Sets `aria-invalid`.

idstring—

Lands on the GROUP, not on a box. Part of `GdField`'s aria contract — accepted in the shape the field hands its slot.

describedBystring—

Ids of the hint and error that describe the field. Also on the group, so a failure is read once rather than once per digit.

Events

complete[code: string]

Fires the instant the last digit lands — from typing, pasting or an OS autofill — so the page can verify without a second tap.

update:modelValue[value: string]

Every change, including deletions.

Usage Guidelines

  • Use this for a one-time code and nothing else. A PIN, a serial or a licence key is a text input.
  • Verify on @complete, not on a submit button. The button is a fallback for the case where the code was pasted and then edited.
  • Wrap it in GdField and spread the slot props — v-bind="f" — so the hint and the error describe the group.
  • Set invalid and clear it on the next keystroke. A code entry stuck in red after the user has started retyping is describing the previous attempt.
  • Leave length alone unless the provider sends something other than six digits — the group's accessible name is derived from it.

Behavior & Anatomy

The keyboard model

  • The digits are mono — a code is a machine fact — and each box selects on focus, so overtyping replaces rather than appends.
  • autocomplete="one-time-code" lets the OS offer the code from the message; several digits landing in one box is handled, because that is exactly what autofill does.
  • The group announces itself once ("6-digit code"), not six times.
  • It sits in the sign-in block after the email step — the real OTP flow is deliberately the only way in.

Why the aria lands on the group

id and describedBy both land on the group rather than on the boxes: the control a user sees is the row, no single box is the thing "that code was wrong" is about, and describing all six would have a screen reader read the failure once per digit. The group keeps its own aria-label either way — a <label for> can only bind to a labelable element, never to a group, so the group has to state its own name.

Navigate

Esc