Forms & Inputs
OTP
A one-time-code field: a row of single-character boxes that behave as one input, with typing, pasting and deletion handled across them.
A one-time-code field. The boxes look separate but behave as one input: typing
advances, Backspace retreats, and a pasted code fills from the box it landed on.
It is form-associated, so it submits under its name like any native control.
Preview
Section titled “Preview”<nana-otp length="6"></nana-otp> Installation
Section titled “Installation”npm install @nana-tec/ui-componentsimport "@nana-tec/ui-components/otp";Give it a length and a name. The value is the characters entered so far, so
a partially typed code reads back as a short string.
<nana-otp length="4" name="code"></nana-otp> Letters as well as digits
Section titled “Letters as well as digits”alphanumeric widens what the boxes accept and switches the on-screen keyboard
away from the numeric one. Anything outside the accepted set is dropped rather
than rejected, so pasting "12 34-56" still fills six digit boxes.
<nana-otp length="5" alphanumeric></nana-otp> Grouping
Section titled “Grouping”A long run of boxes is hard to carry from a message, so six splits as 3-3 and
eight as 4-4 on its own. group-size sets the split yourself, and separator
changes the mark. The mark is hidden from assistive tech, so the code is still
announced as characters rather than punctuation.
<nana-otp length="6"></nana-otp> <nana-otp length="6" group-size="2" separator="·"></nana-otp> Masked
Section titled “Masked”masked renders the characters as dots, for a code that should not be read over
a shoulder.
<nana-otp length="4" masked></nana-otp> Required
Section titled “Required”required fails constraint validation until every box is filled, so a native
form will not submit a half-entered code.
<form><nana-otp length="4" name="code" required></nana-otp></form> Keyboard
Section titled “Keyboard”| Key | Result |
|---|---|
| A character | Fills the box and moves to the next |
| Backspace | Clears the box, or clears the previous one and moves back if already empty |
| ← / → | Moves between boxes |
| Home / End | Jumps to the first or last box |
| Paste | Fills from the current box onward, ignoring separators |
Properties
| Property | Attribute | Type | Default | Description |
|---|---|---|---|---|
alphanumeric | alphanumeric | boolean | false | Accept letters as well as digits. |
disabled | disabled | boolean | false | |
groupSize | group-size | number | 0 | How many boxes sit between separators. 0 picks a split that suits the length — six reads as 3-3, which is far easier to carry from a message than one run of six. |
label | label | string | 'One-time code' | Labels the group for assistive tech. |
length | length | number | 6 | How many characters the code has. |
masked | masked | boolean | false | Render the characters as dots. |
name | name | string | '' | Submitted under this name. |
required | required | boolean | false | |
separator | separator | string | '-' | The mark drawn between groups. |
value | value | string | '' | The code entered so far. |
Events
| Event | Description |
|---|---|
nana-input | On every change; detail: { value: string } |
nana-complete | Once every box is filled; detail: { value: string } |
CSS parts
| Part | Description |
|---|---|
::part(base) | The row of boxes |
::part(slot) | One character box |
::part(separator) | The mark drawn between groups |
CSS custom properties
| Property | Description |
|---|---|
--nana-otp-gap | Space between the boxes |
--nana-otp-group-gap | Space around a separator |
--nana-otp-separator-color | Colour of the separator |
--nana-otp-size | Width and height of one box |
--nana-otp-bg | Box background |
--nana-otp-color | Character colour |
--nana-otp-font-size | Character size |
--nana-otp-radius | Box corner radius |
--nana-otp-border-color | Box border colour |
Events
Section titled “Events”| Event | Type | Description |
|---|---|---|
nana-input | CustomEvent | The code changed; detail.value is the code so far. |
nana-complete | CustomEvent | Every box is filled; detail.value is the whole code. |
Accessibility
Section titled “Accessibility”The host is a group labelled by label, and each box names its own position
(“One-time code, character 3 of 6”) so a screen reader announces where focus
landed. The first box carries autocomplete="one-time-code", which lets a
platform offer a code it received by SMS.