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
modelValuestring""The code so far, as `v-model`. Non-digits are stripped and the string is clamped to `length`.
lengthnumber6How 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
GdFieldand spread the slot props —v-bind="f"— so the hint and the error describe the group. - Set
invalidand clear it on the next keystroke. A code entry stuck in red after the user has started retyping is describing the previous attempt. - Leave
lengthalone 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.