Skip to content
Forms, switch product

One-time Code

One-time Code widgets are Input Fields for the digits of a verification code sent by text message or email. They draw one box per digit over a single text input, so paste, autofill of codes from messages, password managers and screen readers work as in any text field.

otp.ts
import { gui } from '@golemui/gui-shared';
export default [
gui.inputs.otp('verificationCode', {
label: 'Verification code',
}),
];
otp.json
{
"$schema": "https://golemui.com/schemas/form.schema.json",
"form": [
{
"kind": "input",
"type": "otp",
"path": "verificationCode",
"label": "Verification code"
}
]
}

The value is a string of digits, so a code can start with a zero. Anything that isn’t a digit is dropped: a pasted 123-456 becomes 123456. The digits fill in order, and Backspace removes the last one.

Use these props to customize your One-time Code widget.

proptypedescription
groupsnumber[]Splits the boxes into groups with a gap between them, such as [3, 3]. The sizes must add up to the code’s length
hintstringA description to display below the label

The code’s length is not a prop: it is the validator’s exactLength, 6 without one. See Length.

Use the property hint to add a description.

otp.ts
import { gui } from '@golemui/gui-shared';
export default [
gui.inputs.otp('verificationCode', {
hint: 'We sent it to your phone.',
label: 'Verification code',
}),
];
otp.json
{
"$schema": "https://golemui.com/schemas/form.schema.json",
"form": [
{
"kind": "input",
"type": "otp",
"path": "verificationCode",
"label": "Verification code",
"props": {
"hint": "We sent it to your phone."
}
}
]
}

Use the property groups to split the boxes into groups, as many codes are printed: [3, 3] draws a 6-digit code as 3 and 3. Groups only change how the code looks, never the value. Sizes that don’t add up to the code’s length are ignored.

otp.ts
import { gui } from '@golemui/gui-shared';
export default [
gui.inputs.otp('verificationCode', {
groups: [3, 3],
label: 'Verification code',
}),
];
otp.json
{
"$schema": "https://golemui.com/schemas/form.schema.json",
"form": [
{
"kind": "input",
"type": "otp",
"path": "verificationCode",
"label": "Verification code",
"props": {
"groups": [
3,
3
]
}
}
]
}

The code is as long as the validator’s exactLength, 6 by default. Set it for a code of another length, such as a 4-digit PIN.

otp.ts
import { gui } from '@golemui/gui-shared';
export default [
gui.inputs.otp('pin', {
label: 'PIN',
validator: {
required: true,
exactLength: 4,
messages: {
required: 'Enter your PIN',
invalid: 'Enter your PIN',
exactLength: 'Your PIN has 4 digits',
},
},
}),
];
otp.json
{
"$schema": "https://golemui.com/schemas/form.schema.json",
"form": [
{
"kind": "input",
"type": "otp",
"path": "pin",
"label": "PIN",
"validator": {
"type": "string",
"required": true,
"exactLength": 4,
"messages": {
"required": "Enter your PIN",
"invalid": "Enter your PIN",
"exactLength": "Your PIN has 4 digits"
}
}
}
]
}

One-time Codes take a string validator. Its exactLength sets the length of the code, and makes a partial code invalid. Word each error with messages: exactLength for a partial code, and required and invalid for an empty one, since a code the user never touched has no value. Type three digits below, then leave the field.

otp.ts
import { gui } from '@golemui/gui-shared';
export default [
gui.inputs.otp('verificationCode', {
label: 'Verification code',
validator: {
required: true,
exactLength: 6,
messages: {
required: 'Enter the code',
invalid: 'Enter the code',
exactLength: 'Enter all 6 digits',
},
},
}),
];
otp.json
{
"$schema": "https://golemui.com/schemas/form.schema.json",
"form": [
{
"kind": "input",
"type": "otp",
"path": "verificationCode",
"label": "Verification code",
"validator": {
"type": "string",
"required": true,
"exactLength": 6,
"messages": {
"required": "Enter the code",
"invalid": "Enter the code",
"exactLength": "Enter all 6 digits"
}
}
}
]
}

See Validators for every rule of the string validator.

One-time Codes can be styled as explained in the Styling Guide.

Following you will find a list with the CSS Variables and a quick description of what you will style.

CSS VariableDescription
--gui-otp-box-sizeWidth of each box. Defaults to --gui-widget-size, the height of a field
--gui-widget-sizeHeight of the boxes
--gui-bg-surfaceBackground of the boxes
--gui-border-strongBorder of the boxes, and the line between groups
--gui-radius-mdBorder radius of the boxes
--gui-font-lgSize of the digits
--gui-border-focusBorder of the box the next digit goes in, while focused
--gui-intent-errorBorder of the boxes when invalid

This is the anatomy of the One-time Code widget in case you want to use your CSS styles.

otp-anatomy.html
<gui-otp-input class="gui-otp gui-field">
<gui-otp class="gui-field">
<label class="gui-label" for="fieldUid" id="fieldUid_label">
<span class="gui-label__text">Verification code</span>
<div class="gui-widget-hint" id="fieldUid_hint" aria-hidden="true">
We sent it to your phone.
</div>
</label>
<div class="gui-widget">
<div class="gui-otp__control" dir="ltr">
<div class="gui-otp__boxes" aria-hidden="true">
<span class="gui-otp__group">
<span class="gui-otp__box gui-otp__box--filled">4</span>
<span class="gui-otp__box gui-otp__box--filled">8</span>
<span class="gui-otp__box gui-otp__box--active"></span>
<span class="gui-otp__box"></span>
<span class="gui-otp__box"></span>
<span class="gui-otp__box"></span>
</span>
</div>
<input
type="text"
class="gui-otp__input"
inputmode="numeric"
autocomplete="one-time-code"
autocapitalize="off"
autocorrect="off"
spellcheck="false"
id="fieldUid"
aria-describedby="fieldUid_hint"
/>
</div>
</div>
<div class="gui-validator gui-validator--empty" id="fieldUid_errors" role="alert"></div>
</gui-otp>
</gui-otp-input>